我正在编写一个简短的程序来测试从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)
答案 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库。这部分需要您进行研究并弄清楚。