具有共享标志的重定位编译问题

时间:2018-09-06 11:42:19

标签: c linux gcc

我有一个用C语言编写的程序,该程序使用GSL集成ODE系统,并将结果数据存储在数组中。代码是问题的结尾,但是如您所见,这实际上并不是问题所在。

在C代码之后,我使用Python脚本使用ctypes将数组指针传递到C代码中,因为以后我想绘制和处理数组数据。所有这些都很好,它适用于小型测试程序。但是要这样做,我需要使用gcc创建一个共享库。这是出问题的地方。

当我使用

进行编译时
    gcc ctest.c -o ctest.o  -std=c11 -Wall -g -lgsl -lgslcblas -lm

代码工作正常。我有一个主要功能,该功能可以复制Python脚本进行测试,并且没有任何中断。仅供参考,-lgsl-lgslcblas标志用于使链接器停止抱怨缺少GSL声明。但是当我尝试使用

创建共享库时
    gcc ctest.c -o ctest.o  -std=c11 -Wall -g -lgsl -lgslcblas -lm -fPIC -Wl,-shared,-soname,ctest.so

gcc吐出此错误:

    /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

哪个让我感到困惑。我在网上环顾四周,这似乎是对象初始化的问题,这对我来说仍然很奇怪,因为我只使用内置类型来创建数组,除非GSL搞砸了。

#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 个答案:

答案 0 :(得分:0)

感谢安德鲁·亨利(Andrew Henle),该问题已解决。使用

拆分编译和链接
gcc -c -std=c11 -fPIC -g -o ctest.o ctest.c && gcc -o libctest.so ctest.o -lgsl -lgslcblas -lm -shared

产生一个可由Python调用的共享可执行文件(无论如何通过ctypes)。我不确定为什么,但是使用-shared的工作方式与通过-Wl,-shared向链接器传递命令相反。