关于Fortran调用C++函数的小结

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

关于Fortran调用C++函数的小结

2017-3-12

背景

工作中遇到了需要在Fortran代码中调用C++提供的函数的情况。

通过在网上查阅资料,总结了实现方法,制作了一个实例。

工具

集成开发环境是VS2010。由于默认安装模式下的VS2010是无法编译调试Fortran的,所以又补充安装了Intel(R) Virual Fortran 2011(英特尔可视化Fortran编译器)。

参考资料分析

本文需要用到Fortran与C/C++的混合编程,Fortran和C/C++分别编译各自的功能模块源代码,得到各自的目标文件(.obj),然后集成链接这些obj 文件生成一个统一的可执行文件,实现对对方函数的调用,数据交换通过约定接口来实现[1]。

C++代码中函数说明前需要用到extern关键字,说明函数可以在本模块或其它模块中使用[2]。extern与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非[3]。

要在Fortran中调用C++的函数,意味着Fortran项目对C++项目产生了依赖关系,如果项目依赖项未设置会导致类似“无法解析的外部符号_XXX,该符号在函数_XX 中被引用”的错误。另外还要保证Fortran与C++项目的运行库设置都是“多线程调试”[4]。

实现过程

创建Fortran项目

1)启动VS2010,新建一个Fortran控制台应用程序,名称为Console1。

2)在该项目下的Source Files下添加一个新文件Source1.f90。

3)在Source1.f90中写入如下代码:

program main

implicit none

interface

subroutine SUB(a,b)

!DEC$ ATTRIBUTES C,ALIAS:'_sub'::SUB

!DEC$ ATTRIBUTES reference::a,b

integer a , b

end subroutine SUB

end interface

integer(4) a,b,c

a=100

b=1

write(*,*) "开始调用C++里的函数SUB"

call SUB(a,b)

read(*,*)

end program main

注:接口中为_sub这个来自于C++的函数起了个别名SUB,所以在后面调用SUB时其实就是调用_sub。

在接口中还规定了a和b两个参数的传递方式是传引用。

创建C++项目

在解决方案资源管理器中的“解决方案”处右键,添加一个新建项目,在新建窗口中选中Win32控制台应用程序,输入项目名称Cpp2。在随后弹出的应用程序设置中选择应用程序类型为静态库。

在项目的头文件中新建一个sub.h,在其中输入如下代码:

//sub.h

#ifndef _SUB_H

#define _SUB_H

extern"C"void_cdecl sub(int *a,int *b);

#endif

注:在头文件中使用#ifdef和#ifndef是非常重要的,可以防止双重定义的错误[5]。

在项目的源文件中新建一个sub.cpp,在其中输入如下代码:

//sub.cpp

#include"stdafx.h"

#include"sub.h"

#include

extern"C"void_cdecl sub(int *a,int *b)

{

std::cout<<"C++: 已经进入C++的函数内部\n"<<"a="<<*a<<",

b="<<*b<

std::cout<<"a - b = "<<(*a - *b)<

}

注:extern表示这个函数可以被外部使用;"C" 表示使用C的方式编译、生成,这样生成的函数名就会是_sub,而不是按C++默认的方式变成_sub@数字;_cdecl表示编译生成的obj文件中函数名为混合大小写格式,本例中的sub本来就全是小写,所以会变成_sub;另外注意:这里参数是指针,取值要用*a和*b。

设置Fortran项目的项目依赖项

在Console1项目上右键,选择项目依赖项,在弹出窗口中依赖项页内选中Cpp2,切换到生成顺序页,可以看到Cpp2排在Console1前面。

设置运行库

1)设置Fortran项目的运行库,在Console1项目上右键选择属性,然后找到【配置属性】

【Fortran】【Libraries】【Runtime Library】,设置其值为Debug Multithreaded(/libs:static/threads/dbglibs)即多线程调试。

2)设置C++项目的运行库,在Cpp2项目上右键选择属性,找到【配置属性】【C/C++】【代

码生成】【运行库】,设置其值为多线程调试(/MTd)。

生成项目

1)在解决方案上右键选择重新生成解决方案。

2)在解决方案所在的Console1文件夹下找到Debug文件夹,可以看到其中有一个Cpp2.lib

文件,这个静态库文件就是Cpp2项目生成的。

3)在Console1\Console1\Debug文件夹下可以看到Console1.exe文件,这个可执行文件是

Console1项目生成的。

注:如果要单独生成Cpp2,可以在Cpp2项目上右键选择重新生成。如果在Console1项目上右键选择重新生成,因为前文设置了项目依赖项的关系,Cpp2也会被生成。

启动调试

按下F5,启动调试。可以看到调试成功。

相关文档
最新文档