对 'd1mach_' 的未定义引用
undefined reference to 'd1mach_'
我正在尝试 link 使用 c++ 的 fortran 子例程,但不能完全弄清楚这里到底出了什么问题:
fortran 子例程调用一些函数,例如。 d1mach 或 xermsg,它们未在 fortran 子例程中定义,但在外部调用。编译时报错"undefined reference to d1mach_"(or xermsg)。
我尝试 linking 一个我认为可能包含上述功能的库(库中似乎有一个名为 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)
这是调用未声明函数 xermsg 的 fortran 子例程的声明。
我 link 库使用 -L/path/lib 指令但无济于事。
该子程序是计算一个数学函数,是slatec代码的一部分。
请告诉我您可能需要的其他信息。
问题仍然存在的原因可能仅仅是因为您的 lib3j6j9j.a
没有包含必要的文件(例如 d1mach)。其实我们可以直接编译需要的文件,所以我把过程总结如下:
1) 从 Netlib/Slatec 页面 (here or here) 下载 drc3jm.f
(计算 3j-符号)和依赖项。解压缩存档文件以获取 Fortran 文件 (*.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-a)我们也可以把这些*.f做成库,用C++代码link,例如:
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
您也可以使用在线工具获得相同的结果,例如 here。
但根据情况,使用其他库可能更简单。一种方法是使用相应的 GSL 例程 (here) 作为
#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;
}
这里你需要link必要的GSL库(例如g++ test.cpp -lgsl
或g++ test.cpp /usr/lib64/libgsl.so.0 /usr/lib64/libgslcblas.so.0
等)。
另一种方法是使用最新程序 WIGXJPF (the related paper is here)。我试了一下,它似乎非常容易安装(只有一个 make
)和使用。比如进入example/
目录,尝试gcc -I../inc csimple.c ../lib/libwigxjpf.a
。
根据上述论文,该程序可能会提供一些准确性和性能优势。
(*) 更多详情请见the Netlib/FAQ page(感谢评论中的@VladimirF)。我们可以在 Slatec 中使用原始的 d1mach.f 等,但我们需要修改它们以获得正确的机器相关常量。 d1mach.f 等上面的 BLAS 版本自动处理这个,所以它们更方便。
我正在尝试 link 使用 c++ 的 fortran 子例程,但不能完全弄清楚这里到底出了什么问题: fortran 子例程调用一些函数,例如。 d1mach 或 xermsg,它们未在 fortran 子例程中定义,但在外部调用。编译时报错"undefined reference to d1mach_"(or xermsg)。 我尝试 linking 一个我认为可能包含上述功能的库(库中似乎有一个名为 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)
这是调用未声明函数 xermsg 的 fortran 子例程的声明。
我 link 库使用 -L/path/lib 指令但无济于事。 该子程序是计算一个数学函数,是slatec代码的一部分。
请告诉我您可能需要的其他信息。
问题仍然存在的原因可能仅仅是因为您的 lib3j6j9j.a
没有包含必要的文件(例如 d1mach)。其实我们可以直接编译需要的文件,所以我把过程总结如下:
1) 从 Netlib/Slatec 页面 (here or here) 下载 drc3jm.f
(计算 3j-符号)和依赖项。解压缩存档文件以获取 Fortran 文件 (*.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-a)我们也可以把这些*.f做成库,用C++代码link,例如:
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
您也可以使用在线工具获得相同的结果,例如 here。
但根据情况,使用其他库可能更简单。一种方法是使用相应的 GSL 例程 (here) 作为
#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;
}
这里你需要link必要的GSL库(例如g++ test.cpp -lgsl
或g++ test.cpp /usr/lib64/libgsl.so.0 /usr/lib64/libgslcblas.so.0
等)。
另一种方法是使用最新程序 WIGXJPF (the related paper is here)。我试了一下,它似乎非常容易安装(只有一个 make
)和使用。比如进入example/
目录,尝试gcc -I../inc csimple.c ../lib/libwigxjpf.a
。
根据上述论文,该程序可能会提供一些准确性和性能优势。
(*) 更多详情请见the Netlib/FAQ page(感谢评论中的@VladimirF)。我们可以在 Slatec 中使用原始的 d1mach.f 等,但我们需要修改它们以获得正确的机器相关常量。 d1mach.f 等上面的 BLAS 版本自动处理这个,所以它们更方便。