安靖 发表于 2017-7-26 11:51:53

C++调用Fortran静态库中的函数

c++代码中调用由fortran编译的静态库函数在windows(编译器vs2012+intel visual fortran 2013)下,可以成功调用,运行结果正确。
但是移植到linux(编译器c++ f95)下时,在链接时找不到静态库中的函数。

因为fortran代码比较老,所以最好不要对fortran源码进行改动。
附件为测试代码

Linking CXX executable ../bin/Main
CMakeFiles/Main.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x3e): undefined reference to `ADD'
#include <cstdio>

extern "C" void ADD(double *, double *, double *);

int main(int argc, char** argv)
{
        double a=10;
        double b=1;
        double sum;
        ADD(&a,&b,&sum);
        printf("a + b = %lf\n", sum);
        return 0;
}



      subroutine add(a, b, sum)
      real(8) a
      real(8) b
      real(8) sum
      
      sum = a + b
      end






fcode 发表于 2017-7-26 19:10:14

subroutine add(a, b, sum) Bind(C,Name="ADD")
real(8) a
real(8) b
real(8) sum

sum = a + b
end

pasuka 发表于 2017-7-26 22:25:31

Mix C Fortran - Ubuntu中文
http://wiki.ubuntu.org.cn/Mix_C_Fortran
Compiling Fortran - Ubuntu中文
http://wiki.ubuntu.org.cn/Compiling_Fortran

安靖 发表于 2017-7-27 10:53:00

fcode 发表于 2017-7-26 19:10
subroutine add(a, b, sum) Bind(C,Name="ADD")
real(8) a
real(8) b


感谢你的回答。
按照你的修改,确实是可以生成可执行程序,且结果正确。
不过有没有不修改fortran代码的方式呢

fcode 发表于 2017-7-27 11:13:02

不修改fortran的话,就修改C++的符号名,但是这可能因为不同编译器的符号修饰不同,而导致代码不通用。

请看如下截图,根据 nm 获得符号名。再对应修改 cpp 代码即可。

安靖 发表于 2017-7-27 12:03:00

可能理解不是太准确,但是我想混合编程最主要有两点:
1、注意数据类型的一致。可参考3楼中链接。
2、注意函数名的一致。可以用nm查看生成的对象文件(如*.o)或者库(如*.a)中的函数名字。当链接出现问题时,用nm查看下就应该很明白了。

重点讲讲如何保持函数名一致。
1、就是按照2楼的方法。 保证了生成的库文件中的函数名为ADD,因此,c++在链接时就可以找到函数ADD。采用这种方法应该是最一劳永逸的,当前前提是fortran编译器支持,另外允许你修改fortran代码。

2、如果由于客观条件的限制,无法修改fortran源码时,那么就要先用nm命令查看下生成的对象中函数的真实名字(我估计跟编译器类型或者平台之类的都有关系,这才导致我原来的程序在windows下可以,在linux下就不行了)。
我这里生成的库中函数的名字是add_,所以只需将c++的代码中用到fortran函数的地方就行修改。
#include <cstdio>

extern "C" void add_(double *, double *, double *);

int main(int argc, char** argv)
{
        double a=10;
        double b=1;
        double sum;
        add_(&a,&b,&sum);
        printf("a + b = %lf\n", sum);
        return 0;
}

个人理解,如有偏差,大家多多指正。有些专业术语也可能不太准确。

安靖 发表于 2017-7-27 12:06:49

fcode 发表于 2017-7-27 11:13
不修改fortran的话,就修改C++的符号名,但是这可能因为不同编译器的符号修饰不同,而导致代码不通用。

请 ...

多谢。 早知道刷新下网页了,不用傻傻地又重复了一遍你说的。

你的回答很直观!(手动点赞)
页: [1]
查看完整版本: C++调用Fortran静态库中的函数