Fortran Coder

查看: 164|回复: 6

[混编] C++调用Fortran静态库中的函数

[复制链接]

62

帖子

14

主题

0

精华

专家

F 币
545 元
贡献
320 点
发表于 2017-7-26 11:51:53 | 显示全部楼层 |阅读模式
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'
[C++] 纯文本查看 复制代码
#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;
}



[Fortran] 纯文本查看 复制代码
      subroutine add(a, b, sum)
      real(8) a
      real(8) b
      real(8) sum
      
      sum = a + b
      end






test.zip

5.98 KB, 下载次数: 1

测试例子

回复

使用道具 举报

1126

帖子

12

主题

5

精华

论坛跑堂

Fcode跑堂

F 币
975 元
贡献
820 点

新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2017-7-26 19:10:14 | 显示全部楼层
[Fortran] 纯文本查看 复制代码
subroutine add(a, b, sum) Bind(C,Name="ADD")
real(8) a
real(8) b
real(8) sum

sum = a + b
end

341

帖子

2

主题

0

精华

大宗师

F 币
2391 元
贡献
1445 点

水王勋章元老勋章热心勋章

发表于 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

62

帖子

14

主题

0

精华

专家

F 币
545 元
贡献
320 点
 楼主| 发表于 2017-7-27 10:53:00 | 显示全部楼层
fcode 发表于 2017-7-26 19:10
[mw_shl_code=fortran,true]subroutine add(a, b, sum) Bind(C,Name="ADD")
real(8) a
real(8) b

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

1126

帖子

12

主题

5

精华

论坛跑堂

Fcode跑堂

F 币
975 元
贡献
820 点

新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

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

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

nm.png

62

帖子

14

主题

0

精华

专家

F 币
545 元
贡献
320 点
 楼主| 发表于 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函数的地方就行修改。
[C++] 纯文本查看 复制代码
#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;
}


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

62

帖子

14

主题

0

精华

专家

F 币
545 元
贡献
320 点
 楼主| 发表于 2017-7-27 12:06:49 | 显示全部楼层
fcode 发表于 2017-7-27 11:13
不修改fortran的话,就修改C++的符号名,但是这可能因为不同编译器的符号修饰不同,而导致代码不通用。

请 ...

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

你的回答很直观!(手动点赞)
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

QQ|捐赠本站|Archiver|关于我们 About Us|QQ群|Fcode

GMT+8, 2017-10-19 17:10

Powered by Discuz! X3.2

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表