对’d1mach_’的未定义引用

我正在尝试将一个fortran子例程与c ++链接起来,但是不能完全弄清楚这里到底出了什么问题:fortran子例程调用了一些函数,例如。 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代码的一部分。

请告诉我您可能需要的其他信息。

问题持续存在的原因可能仅仅是因为您的lib3j6j9j.a不包含必要的文件(例如d1mach)。 实际上,我们可以直接编译必要的文件,因此我将总结以下过程:

1)从Netlib / Slatec页面( 此处或此处 )下载drc3jm.f (计算3j符号)和依赖项。 解压缩归档文件以获取Fortran文件(* .f)。

 tar xvf netlibfiles.tgz 

2)删除d1mach.fi1mach.fr1mach.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-a)我们还可以将这些* .f作为库并与C ++代码链接,例如,如下所示:

 gfortran -c *.f ar rv mylib.a *.o g++ testc.cpp mylib.a -lgfortran 

主程序(testc.cpp)

 #include  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  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 -lgslg++ 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)。 我们可以在Slatec中使用原始的d1mach.f等,但我们需要修改它们以获得正确的机器相关常量。 以上BLAS版本的d1mach.f等自动处理,因此它们更方便。