Visual Studio下Fortran与C++项目混合编译调用实现方法
Visual Studio 下MSVC C++ 调用 Intel Fortran 子程序对接方案
你设想的「解决方案下分两个独立项目,Fortran代码单独放一个项目、C++代码放另一个项目,通过extern "C"声明接口」的思路完全可行,也是这类跨语言混合编译场景下维护成本最低、最稳定的方案,具体配置步骤如下:
一、Fortran 静态库项目配置(Intel Fortran 编译器)
不要把Fortran编成动态库(DLL),静态库是和MSVC MFC项目对接最稳的选择,可避免运行时初始化、导出符号修饰、运行库依赖的一堆坑:
- 新建Intel Fortran项目时直接选**静态库(.lib)**模板,把所有Fortran源码、include头文件全部导入项目,先按原有Fortran项目的include搜索路径、预处理器定义配好,确保Fortran项目单独就能编译通过,先解决内部源码的依赖问题。
- 改造所有需要给C++调用的Fortran子程序,统一C兼容的调用约定:
- 子程序开头加
use iso_c_binding引入标准C类型绑定模块,所有跨语言传递的参数、返回值,全部用iso_c_binding里定义的定长类型(比如c_int对应C的int、c_double对应C的double、c_float对应C的float),不要用Fortran默认的无kind修饰的integer/real,避免不同编译器默认类型长度不匹配踩内存。 - 子程序定义末尾加
bind(C, name="你要暴露给C的精确函数名"),彻底规避Fortran编译器默认的名字修饰(比如老版本Fortran会自动给函数名加下划线、转全大写,导致C++侧链接找不到符号)。
示例改造:
! 改造前的原始Fortran子程序 ! subroutine calc_val(a, len, res) ! implicit none ! integer :: len ! real*8 :: a(len), res ! 改造后可被C调用的版本 subroutine calc_val(a, len, res) bind(C, name="calc_val") use iso_c_binding implicit none integer(c_int), intent(in) :: len real(c_double), intent(in) :: a(len) real(c_double), intent(out) :: res ! 原有计算逻辑保持不变 end subroutine - 子程序开头加
- 项目属性切到「所有配置、所有平台」,找到
Fortran -> Libraries -> Runtime Library选项,选和后续C项目完全一致的运行库:C用/MD(多线程DLL)就选对应多线程DLL,C++用/MDd(多线程调试DLL)就选对应调试版DLL,/MT/MTd同理,两边不匹配必出链接错误。 - 编译项目,生成对应的.lib静态库文件。
二、C++ MFC 项目配置(MSVC 编译器)
- 接口声明直接用你提到的
extern "C"即可,注意Fortran默认所有参数都是传地址(传指针),除非你在Fortran侧特意给参数加value修饰指定传值,所以声明时参数类型要对应成指针:// 放在全局头文件里即可,需要调用Fortran子程序的类直接引这个头 extern "C" { // 对应上面改造的Fortran calc_val子程序 void calc_val(double* a, int* len, double* res); } - 项目关联配置不用手动填库路径,最省事的方法:右键C项目 -> 「添加」->「引用」,勾选同解决方案下的Fortran静态库项目,VS会自动处理编译顺序(改Fortran代码会自动先重编Fortran库再编C)、库搜索路径、链接依赖,不用每次手动拷lib文件。
- 同样在C++项目属性里确认运行库选项和Fortran侧完全一致。
三、常见踩坑点提前规避
- 多维数组传参注意存储顺序:Fortran是列优先存储,C++是行优先存储,二维/多维数组传过去之后索引逻辑要对应调整,不然计算结果全错。
- 字符串传参不要直接传MFC的CString:Fortran的
bind(C)接口只认C风格\0结尾的char数组,如果是Unicode编码的CString先转成UTF8/GB2312的char*再传,Fortran侧用c_char数组接收。 - 内存分配和释放要在同一边:不要在Fortran侧分配堆内存返回指针给C释放,两边堆管理器不通用会直接崩溃,数组、缓冲区尽量在C侧分配好,传首地址给Fortran用。
- 如果遇到链接报找不到函数符号,打开VS开发人员命令提示符,用
dumpbin /exports 你的fortran.lib命令查看lib里实际导出的符号名,和你C++声明的函数名对一下,用了标准bind(C)写法的话两边名字应该完全一致,没有多余的下划线、大小写差异。
内容的提问来源于stack exchange,提问作者YS_Jin
相关产品推荐
相关产品推荐

