asked    Bernie     2018-10-22       c       71 view        1 Answer

[SOLVED] Relocation compiling issue with shared flags

I have a program in C that uses the GSL to integrate an ODE system, and store the resulting data in arrays. The code is at the end of the question, but as you'll see it's not really the issue here.

Secondary to the C code, I use a Python script to pass the array pointers into the C code using ctypes, since I later want to plot and manipulate the array data. All of which is fine, it worked with small test programs. But to do so, I need to create a shared library using gcc. Here's where things go wrong.

When I compile with

    gcc ctest.c -o ctest.o  -std=c11 -Wall -g -lgsl -lgslcblas -lm

the code works fine. I have a main function that replicates the Python script for testing, and nothing breaks. FYI, the -lgsl and -lgslcblas flags are used to make the linker stop complaining about GSL declarations being missing. But when I try to create the shared library with

    gcc ctest.c -o ctest.o  -std=c11 -Wall -g -lgsl -lgslcblas -lm -fPIC -Wl,-shared,-soname,ctest.so

gcc spits out this error:

    /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
    (.text+0xe): undefined reference to `__init_array_start'
    /usr/bin/x86_64-linux-gnu-ld: /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): relocation R_X86_64_PC32 against undefined hidden symbol `__init_array_start' can not be used when making a shared object
    /usr/bin/x86_64-linux-gnu-ld: final link failed: Bad value
    collect2: error: ld returned 1 exit status

Which baffles me. I looked around online, and it seems to be a problem with object initialization, which is still odd to me since I only use built in types for array creation, unless it's GSL screwing up.

#include <stdio.h>
#include <math.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_complex_math.h>

#define pi M_PI

//#define HAVE_INLINE

typedef struct funcParams {
    double I;
    double J;
    double s;
} funcParams;

int diff (double t, const double y[], double dy[], void * params) {

    #define I() IJs.I
    #define J() IJs.J
    #define s() IJs.s

    #define w1 y[0]
    #define w2 y[1]
    #define w3 y[2]
    #define e1 y[3]
    #define e2 y[4]
    #define e3 y[5]
    #define e4 y[6]

    t = 0;

    funcParams IJs = *(funcParams*) params;

    dy[0] = 2*pi * ( (1-J() /I() )*( 6*(1-2*e1*e1-2*e2*e2)*(e2*e3+e1*e4) - w2*w3) + w3*s() );
    dy[1] = 0;
    dy[2] = 2*pi * ( (J() /I() -1)*(12*(e1*e3-e2*e4)*(e2*e3+e1*e4) - w1*w2) - w1*s() );
    dy[3] = pi * (w3*e2 + w1*e4 - e3*(w2-s()+1));
    dy[4] = pi * (w1*e3 - w3*e1 + e4*(w2-s()-1));
    dy[5] = pi * (-w1*e2 + w3*e4 + e1*(w2-s()+1));
    dy[6] = pi * (-w1*e1 - w3*e3 - e2*(w2-s()-1));

    return GSL_SUCCESS;
}

void quat2C( double* e, double C[3][3]) {

    #undef e1
    #undef e2
    #undef e3
    #undef e4

    #define e1 e[0]
    #define e2 e[1]
    #define e3 e[2]
    #define e4 e[3]

    C[0][0] = 1 - 2*e2*e2 - 2*e3*e3;
    C[0][1] = 2 * (e1*e2 - e3*e4);
    C[0][2] = 2 * (e3*e1 + e2*e4);
    C[1][0] = 2 * (e1*e2 + e3*e4);
    C[1][1] = 1 - 2 * e3*e3 - 2 * e1*e1;
    C[1][2] = 2 * (e2*e3 - e1*e4);
    C[2][0] = 2 * (e3*e1 - e2*e4);
    C[2][1] = 2 * (e2*e3 + e1*e4);
    C[2][2] = 1 - 2 * e1*e1 - 2 * e2*e2;

    return;
}



void timeHistories (double nut0, double x, double vf, int N, double I, double J, double s, double* states, double * nut, double* gamma, double* beta, double* dLambda) {

    funcParams IJs = {I, J, s};
    gsl_odeiv2_system sys = {diff, NULL, 7, &IJs};
    gsl_odeiv2_driver* d = gsl_odeiv2_driver_alloc_y_new(&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);

    double* states_i = (double*)malloc(7*sizeof(double));
    states_i[0] = 0;
    states_i[1] = x;
    states_i[2] = 0;
    states_i[3] = sin(nut0*pi/360);
    states_i[4] = 0;
    states_i[5] = 0;
    states_i[6] = cos(nut0*pi/360);
    double v = 0.0;

    double C[3][3];

    /* retrieve the states at each time. This allows us to modify each of the
       "returned" arrays in the same loop */
    for (int i = 0; i < N; ++i) {

        double vi = i*vf/N; // current revolution value
        printf("vi got\n");
        gsl_odeiv2_driver_apply(d, &v, vi, states_i); // get states
        printf("states got\n");
        quat2C(&states_i[3],C);
        printf("C got\n");

        printf("%d: %f %f %f %f %f %f %f\n", i, states_i[0], states_i[1], states_i[2], states_i[3], states_i[4], states_i[5], states_i[6]);
    }

    return;
}

int main() {

    double I = 450;
    double J = 75;
    int N = gsl_pow_int(2,14);

    double* states = (double*)malloc(N*sizeof(double));
    double* nut = (double*)malloc(N*sizeof(double));
    double* gamma = (double*)malloc(N*sizeof(double));
    double* beta = (double*)malloc(N*sizeof(double));
    double* dLambda = (double*)malloc(sizeof(double));

    double vf = 4;

    double nut0 = 6;
    double x = 20;
    double s = 0;
    timeHistories(nut0, x, vf, N, I, J, s, states, nut, gamma, beta, dLambda);

    return 0;
}

  1 Answer  

        answered    Bridget     2018-10-22      

Thanks to Andrew Henle, the issue has been resolved. Splitting the compilation and linking using

gcc -c -std=c11 -fPIC -g -o ctest.o ctest.c && gcc -o libctest.so ctest.o -lgsl -lgslcblas -lm -shared

produces a shared executable callable by Python (via ctypes, anyway). I'm unsure as to why, but using -shared works as opposed to passing commands to the linker with -Wl,-shared.





Your Answer





 2018-10-22         Vanessa

Developing UCWA applications for Skype for Business Online

I'm trying to develop a simple java client that needs to access Skype for Business APIs in order to setup an online meeting (i.e. I need to retrieve a simple setup meeting URL by invoking an UCWA API).I followed this Microsoft tutorial step-by-step:https://docs.microsoft.com/en-us/skype-sdk/ucwa/developingucwaapplicationsforsfbonlineI have an Office 365 Business Premium license and I configured a custom domain (correctly registered and added at the zone DNS file);I configured and registered my java client app on Azure (taking care to assign required delegated permission for...
 java                     1 answers                     51 view
 2018-10-22         Fabian

npm linked module listed as unmet dependency

I'm linking my-lib to see effects in my-app right away. cd my-lib-foldernpm linkcd ../my-app-foldernpm link my-libThis works as expected. Changes are picked up by my-app and I see the symlink in node_modules. My problem is that in my-app-folder/, npm list --link=true shows up empty. How can I get a list of the linked modules? npm ls my_libmy-app@3.1.0 /Users/path/my_project└── UNMET DEPENDENCY my-lib@3.7.0 npm ERR! missing: my-lib@3.7.0, required by my-app@3.1.0This happens both with Node 8 and 10 and their respective npm versions. OK, I realized that my-lib was somehow ...
 node.js                     1 answers                     50 view
 2018-10-22         Verna

how to refresh token when expired in jwt

I am implementing JWT in my project. I implemented jwt and gave it an expiration time of 1 minute. The jwt that is generated from the api side is during login and the token and expiration details are sent in the result and are stored in local storage. How can I refresh the expired token from API side and send it back again to the client so that it can be stored in local storage and sent for every call using interceptor?this is how I created jwt and gave expiration time// let us suppose this is my inputtokenObject = { User: { username: name, pwd: pwd } };//creating a jwt her...
 angularjs                     2 answers                     55 view