c-对’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页面(herehere)下载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代码链接,例如,如下所示:

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;
}

在这里您需要链接必要的GSL库(例如g test.cpp -lgsl或g test.cpp /usr/lib64/libgsl.so.0 /usr/lib64/libgslcblas.so.0等).

另一种方法是使用最新程序WIGXJPF(相关论文为here).我尝试了一下,它似乎非常容易安装(只有一个品牌)和使用.例如,输入example /目录,然后尝试gcc -I ../ inc csimple.c ../lib/libwigxjpf.a.
根据上述论文,该程序可能会提供一些准确性和性能优势.

(*)有关更多详细信息,请参见the Netlib/FAQ page(在评论中感谢@VladimirF).我们可以在Slatec中利用原始的d1mach.f等,但是我们需要对其进行修改,以获得正确的机器相关常数.上面的d1mach.f等BLAS版本会自动处理此问题,因此更加方便.

上一篇:Linux for ansys中的分段错误


下一篇:error C2039: 'SetDefaultDllDirectories'错误解决办法