【问题标题】:Fortran subroutines produce "Undefined symbols" error when linking to c++ programFortran 子例程在链接到 c++ 程序时产生“未定义符号”错误
【发布时间】:2019-03-26 15:23:43
【问题描述】:

我正在编写一个简短的程序来测试从 c++ 调用 fortran Stripack 库。 c++ 和 fortran 文件均编译成功,但链接时出现错误。

c++代码如下:

#include <iostream>
#include <cmath>

#ifdef __cplusplus
extern"C" {
    #endif
    void trmesh_(int&,float[],float[],float[],int[],int[],int[],int&,int[],int[],float[],int&);
    void trlist2_(int&,int[],int[],int[],int&,int[][3],int&);
    #ifdef __cplusplus
}
#endif


int main(){

// Variables for distributing points on sphere.
  int polar = 16;
  int azimuth = 32;
  int n = polar*azimuth-azimuth+2;
  float radius=1.0;

// Define variables needed by Stripack
  float xs[n];
  float ys[n];
  float zs[n];
  int list[6*(n-2)];
  int lptr[6*(n-2)];
  int lend[6*(n-2)];
  int near[n];
  int next[n];
  float dist[n];
  int ltri[2*n-4][3];
  int lnew;
  int ier;
  int nt;

// Distribute n points on surface of unit sphere .
// xs, ys, zs store x, y, and z components pf each point position.
  zs[0] = 1;
  xs[0] = 0;
  ys[0] = 0;
  zs[n] = -1;
  xs[n] = 0;
  ys[n] = 0;
  for (int ii=1; ii<polar; ii++){
    for (int jj=0; jj<azimuth; jj++){
      zs[(ii-1)*azimuth+jj+1] = radius*cos(ii*M_PI/polar);
      xs[(ii-1)*azimuth+jj+1] = radius*sin(ii*M_PI/polar)*sin(jj*2*M_PI/azimuth);
      ys[(ii-1)*azimuth+jj+1] = radius*sin(ii*M_PI/polar)*cos(jj*2*M_PI/azimuth);
    }
  }

// Call stripack subroutines to obtain list of triangles ltri
  trmesh_(n,xs,ys,zs,list,lptr,lend,lnew,near,next,dist,ier);
  trlist2_(n,list,lptr,lend,nt,ltri,ier);

// Output list of triangles
  for (int ii =0; ii<n; ii++){
    std::cout << ltri[ii][0] << " " << ltri[ii][1] << " " << ltri[ii][2] << std::endl;
  }

}

我编译文件如下:

ifort -c stripack.f90
clang++ -c -O0 -std=c++11 -c -o main.o main.cpp -g
clang++ -o main stripack.o main.o

前两个编译工作正常,但最后一个产生以下结果。好像fortran文件中的子程序找不到标准的fortran函数?我已经尝试过使用 gfortran 并且出现了同样的问题。任何关于正在发生的事情的建议将不胜感激。

Undefined symbols for architecture x86_64:
  "___libm_sse2_sincos", referenced from:
      _trplot_ in stripack.o
      _vrplot_ in stripack.o
  "___svml_sincos2", referenced from:
      _trans_ in stripack.o
  "_for_date_and_time", referenced from:
      _timestamp_ in stripack.o
  "_for_stop_core", referenced from:
      _trmesh_ in stripack.o
      _addnod_ in stripack.o
  "_for_trim", referenced from:
      _timestamp_ in stripack.o
  "_for_write_seq_fmt", referenced from:
      _delnod_ in stripack.o
      _edge_ in stripack.o
      _timestamp_ in stripack.o
      _trlprt_ in stripack.o
      _trmesh_ in stripack.o
      _addnod_ in stripack.o
      _trplot_ in stripack.o
      ...
  "_for_write_seq_fmt_xmit", referenced from:
      _delnod_ in stripack.o
      _edge_ in stripack.o
      _timestamp_ in stripack.o
      _trlprt_ in stripack.o
      _trmesh_ in stripack.o
      _addnod_ in stripack.o
      _trplot_ in stripack.o
      ...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

【问题讨论】:

  • 这已被标记为重复,但我真的认为链接的答案实际上与这个特定问题无关。
  • 如果使用 clang++/g++ 链接 ifort 编译的对象,你需要链接一些 ifort 库,可能需要类似 -L$(YOUR_IFORT_LIB_PATH) -lifport -lifcore -lirc -lsvml

标签: c++ fortran


【解决方案1】:

我将通过示例演示这是一个链接问题,您需要做更多的研究来解决问题,因为您提供的信息不完整。

!fortran code, named as x.f90
subroutine testFDLL(str, n) bind(c, name='testFDLL_as_C')
    use ISO_C_BINDING
    integer(c_int), value :: n
    character(kind=c_char), intent(in) :: str(n)
    write(6,*)" Hello FORTRAN : let us do something ...",str
    return
end

以下 C 代码用于演示(您已经掌握了 C++ 大部分内容)。

//c named as y.c
#include <stdio.h>
#include <string.h>

int main()
{
    void testFDLL_as_C(char *str, int n);
    char str[] = "Hello from C";
    testFDLL_as_C(str, strlen(str));
    return 0;
}

如果你编译和链接使用下面的

ifort -c x.f90
gcc y.c x.o -W -Wall 

取决于 ifort 和操作系统的版本,应该得到类似以下的错误

x.o: In function `testFDLL_as_C':
x.f90:(.text+0x42): undefined reference to `for_write_seq_lis'
x.f90:(.text+0x74): undefined reference to `for_write_seq_lis_xmit'
collect2: error: ld returned 1 exit status

如果您使用

链接,您可能会注意到未定义的引用名称模式与您的相似
gcc y.c x.o -W -Wall -L/path/to/your/ifort_lib -lifcore -ldl

问题应该解决了。取决于您使用的 FORTRAN 功能,您可能需要链接更多 ifort 库。这部分需要你做一些研究和弄清楚。

【讨论】:

  • 感谢您提供非常有帮助的回复。我尝试完全按照您在答案中编写的代码编译代码,并看到了您在链接时给出的错误。不幸的是,我找不到有效的路径,并且我的编译器无法识别 -lifcore-lifport-lirc-lsvml 标志。删除这些标志后,我尝试了-L/opt/intel/-L/opt/intel/bin/-L/opt/intel/lib/-L/opt/intel/include/,但都没有奏效。你能建议我应该寻找什么样的库文件吗?
  • 我也找到了这个答案stackoverflow.com/questions/5663083/…,但使用 gfortran 编译并使用此处建议的 -lgfortran 标志只会导致 library not found for -lgfortran 错误。
  • 更新:我已经设法通过运行以下命令来编译它:clang++ -c -Wall -std=c++11 main.cpp -o main.ogfortran -c stripack.f90 -o stripack.oclang++ main.o stripack.o -o main -L/usr/local/lib/gcc/8/ -lgfortran 不幸的是,程序在调用剥离函数时立即遇到了一个设置错误,但至少它现在编译。
  • 库路径通常与ifort的安装路径有关,在linux上,通常在“which ifort”或“locate libifcore.a”之类的地方,它因机器而异,并且安装到安装。
  • 是的,which ifort 返回了/opt/intel/bin 目录,但该目录和相关目录似乎都不起作用。但至少我现在已经用 gfortran 对其进行了排序——这就足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-15
  • 2012-05-08
  • 2012-06-28
  • 1970-01-01
  • 2014-07-15
  • 2015-09-19
相关资源
最近更新 更多