У меня есть программа на C, которая использует GSL для интеграции системы ODE и сохранения полученных данных в массивах. Код находится в конце вопроса, но, как вы увидите, здесь проблема не в этом.
Вторично к коду C, я использую скрипт Python для передачи указателей массива в код C с помощью ctypes, так как позже я хочу построить и манипулировать данными массива. Все это хорошо, это работало с небольшими тестовыми программами. Но для этого мне нужно создать общую библиотеку, используя 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;
}