Неопределенная ссылка на 'd1mach_'
Я пытаюсь связать подпрограмму фортрана с C++, но не могу понять, что именно здесь не так: подпрограмма фортрана вызывает некоторые функции, например. d1mach или xermsg, которые не определены в подпрограмме fortran, но вызываются извне. При компиляции ошибка "неопределенная ссылка на d1mach_"(или xermsg). Я попытался связать библиотеку, которая, как мне кажется, может содержать указанные функции (кажется, в библиотеке есть файлы с именами d1mach.o и xermsg.o), но та же ошибка все еще сохраняется. Что я могу делать не так?
extern"C" {
void drc3jm_(double *L1,double *L2,double *L3,double *M1,double *M2MIN,
double *M2MAX,double *THRCOF,int *NDIM,int *IER);
}
Это функция, которую я использую для вызова подпрограммы, и я не использовал никаких новых заголовков, кроме iostream
*DECK DRC3JM
SUBROUTINE DRC3JM (L1, L2, L3, M1, M2MIN, M2MAX, THRCOF, NDIM,
+ IER)
CALL XERMSG('SLATEC','DRC3JM','L1-ABS(M1) less than zero or '//
+ 'L1+ABS(M1) not integer.',IER,1)
Это объявление подпрограммы fortran, которая вызывает необъявленную функцию xermsg.
Я связываю библиотеку, используя инструкцию -L /path/ lib, но безрезультатно. Подпрограмма предназначена для вычисления математической функции и является частью slatec-кодов.
Пожалуйста, дайте мне знать, какая другая информация вам может понадобиться.
1 ответ
Причина, по которой проблема сохраняется, может быть просто потому, что ваша lib3j6j9j.a
не включает необходимые файлы (например, d1mach). На самом деле, мы можем скомпилировать необходимые файлы довольно напрямую, поэтому я подведу итоги процедуры ниже:
1) Скачать drc3jm.f
(который вычисляет 3j-символы) и зависимости со страницы Netlib/Slatec ( здесь или здесь). Распакуйте архив, чтобы получить файлы Фортрана (*.f).
tar xvf netlibfiles.tgz
2) Удалить d1mach.f
, i1mach.f
, а также r1mach.f
(если есть). Вместо этого загрузите их альтернативные версии из Netlib / blas (*):
rm -f i1mach.f r1mach.f d1mach.f
wget http://www.netlib.org/blas/i1mach.f
wget http://www.netlib.org/blas/r1mach.f
wget http://www.netlib.org/blas/d1mach.f
3) Скомпилируйте все *.f файлы
gfortran testf.f90 *.f
вместе с основной программой testf.f90 (в свободном формате), например,
program main
implicit none
integer, parameter :: N = 1000
double precision coef( N ), M2min, M2max, M2
integer ier
ier = 0 ; coef(:) = 0.0d0
call DRC3JM( 15.0d0, 30.0d0, 40.d0, 2.0d0, M2min, M2max, coef, N, ier )
print *, "M2min, M2max, ier = ", M2min, M2max, ier
M2 = 2.0d0
print "(a, f20.15)", "coef = ", coef( nint(M2 - M2min+1) ) !! -0.019081579799192
end
Затем запуск исполняемого файла дает желаемый результат.
3-а) Мы также можем сделать их *.f в виде библиотеки и связать их с кодами C++, например, следующим образом:
gfortran -c *.f
ar rv mylib.a *.o
g++ testc.cpp mylib.a -lgfortran
с основной программой (testc.cpp)
#include <cstdio>
extern "C"
double drc3jm_ (double*, double*, double*,
double*, double*, double*, double*, int*, int*);
int main()
{
double* coef;
double L1, L2, L3, M1, M2min, M2max, M2;
int ier, k, N = 1000;
coef = new double [ N ];
L1 = 15.0; L2 = 30.0; L3 = 40.0; M1 = 2.0;
drc3jm_ ( &L1, &L2, &L3,
&M1, &M2min, &M2max, coef, &N, &ier );
printf( "M2min, M2max, ierr = %10.5f%10.5f%d\n", M2min, M2max, ier );
M2 = 2.0;
k = (int)(M2 - M2min + 1.0e-3);
printf( "coef = %20.15f\n", coef[ k ] ); // -0.019081579799192
return 0;
}
Мы можем видеть, что две программы дают одинаковый коэффициент (-0.019081579799192) для
j1=15, j2=30, j3=40, m1=2, m2=2, m3=-4
Вы также можете получить тот же результат с онлайн-инструментом, например, здесь.
Но в зависимости от случаев может быть проще использовать другие библиотеки. Один из подходов заключается в использовании соответствующих подпрограмм GSL ( здесь) в качестве
#include <cstdio>
extern "C"
double gsl_sf_coupling_3j (int two_ja, int two_jb, int two_jc,
int two_ma, int two_mb, int two_mc);
int main()
{
double coef;
coef = gsl_sf_coupling_3j( 30, 60, 80, 4, 4, -8 ); // -0.019081579799205
// NOTE: all j's and m's need to be doubled.
printf( "coef = %20.15f\n", coef );
return 0;
}
Здесь вам нужно связать необходимые библиотеки GSL (например, g++ test.cpp -lgsl
или же g++ test.cpp /usr/lib64/libgsl.so.0 /usr/lib64/libgslcblas.so.0
так далее).
Еще один подход заключается в использовании новейшей программы WIGXJPF (соответствующий документ здесь). Я попробовал это немного, и это кажется чрезвычайно простым в установке (только один make
) и использовать. Например, введите example/
каталог и попробуйте gcc -I../inc csimple.c ../lib/libwigxjpf.a
, Согласно приведенному выше документу, эта программа может предложить некоторые преимущества точности и производительности.
(*) Для получения более подробной информации, пожалуйста, посетите страницу Netlib / FAQ (спасибо @VladimirF в комментарии). Мы могли бы использовать исходный файл d1mach.f и т. Д. В Slatec, но нам нужно изменить их, чтобы получить правильные машинно-зависимые константы. Вышеуказанные версии d1mach.f BLAS и т. Д. Обрабатывают это автоматически, что делает их более удобными.