链接到C ++程序时,Fortran子例程产生“未定义符号”错误

时间:2019-03-26 15:23:44

标签: c++ fortran

我正在编写一个简短的程序来测试从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)

1 个答案:

答案 0 :(得分: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和OS的版本,应出现与以下类似的错误

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库。这部分需要您进行研究并弄清楚。