VS2017下C++与Fortran混合编译unresolved externals问题
VS2017 链接Intel Fortran静态库混合编译问题排查与解决
本次测试目标为搭建Fortran-C++混合编译项目,验证Visual Studio 2017编译器链接Intel Fortran生成的.lib静态库的实现逻辑。
测试示例代码
Fortran端初始代码
!DEC$ IF DEFINED (_DLL) !DEC$ ATTRIBUTES DLLEXPORT :: ADD !DEC$ END IF REAL*8 FUNCTION ADD (A, B, C, D) REAL*8 B,D INTEGER*4 A,C DIMENSION B(4), D(4) ADD = B(A) + D(C) RETURN END
C++端初始代码
#include <iostream> extern "C" {double add_(int *, double[], int *, double[]); } double ar1[4] = { 1.0, 2.0, 3.0, 4.0 }; double ar2[4] = { 5.0, 6.0, 7.0, 8.0 }; int main() { int x, y; double z; x = 3; y = 3; z = add_(&x, ar1, &y, ar2); /* Call Fortran add routine */ /* Note: Fortran indexes arrays 1..n */ /* C indexes arrays 0..(n-1) */ std::cout << z << std::endl; return 0; }
初始配置流程
- 打开Visual Studio,创建C空项目,将上述C代码加入源文件,自动生成对应解决方案
- 在解决方案中新增Fortran静态库项目,将上述Fortran代码加入源文件
- Fortran项目属性 -> Libraries -> Runtime Libraries 设置为Debug multithread dll
- 编译Fortran项目,定位生成的.lib文件所在目录
- C++项目属性 -> linker -> General -> Additional Library Dependencies 中添加上述.lib文件所在目录
- C++项目属性 -> linker -> Input -> Additional dependencies 中添加对应.lib文件名,末尾以分号结尾
- 编译C++项目
初始编译报错
1>------ Build started: Project: Cpp_main, Configuration: Debug Win32 ------ 1>Source.obj : error LNK2019: unresolved external symbol _add_ referenced in function _main 1>C:\Users\Documents\TEST_Project\MixCompile_Test\Mix_compile\Debug\Cpp_main.exe : fatal error LNK1120: 1 unresolved externals 1>Done building project "Cpp_main.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
初始疑问:已在C++项目中配置了.lib文件路径,为何仍无法解析外部函数调用?
排查阶段新报错
2022年6月24日更新:按照指引在VC++目录中添加了Intel Fortran的include和lib目录后,出现新的报错:
1>------ Build started: Project: Cpp_main, Configuration: Debug Win32 ------ 1>LINK : fatal error LNK1104: cannot open file 'msvcprtd.lib' 1>Done building project "Cpp_main.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
最终验证可行配置方案
该问题为VS2017环境下的特殊适配问题,验证环境为Intel ifortran19、MSVC 2017,配置步骤如下:
- 创建C++项目与对应解决方案
- 在解决方案中新增Fortran静态库项目
- 在Fortran项目中添加对应头文件与源代码
- 所有需要被C++调用的Fortran子程序需使用
BIND(C)绑定,引入ISO_C_BINDING内置模块,格式参考如下:
subroutine_name() BIND(C) USE, INTRINSIC :: ISO_C_BINDING ! 子程序业务逻辑 end subroutine
- C++侧函数声明规则:使用Intel Fortran编译器时,函数声明后无需追加下划线,直接通过
extern "C"声明即可,格式为extern "C"{返回值类型 <fortran_subroutine>(参数列表);};注意C侧传入的所有参数需为引用或指针类型,禁止值传递 - C项目编译侧依赖目录配置:
- C项目属性 -> VC++ Directories -> Include Directories 添加
$(IFORT_COMPILER19)\compiler\include; - C项目属性 -> VC++ Directories -> Library Directories 添加
$(IFORT_COMPILER19)\compiler\lib;,需根据VS所选编译平台(Win32/X64)追加\ia32_win或\intel64_win后缀
- C项目属性 -> VC++ Directories -> Include Directories 添加
- C项目链接器侧依赖配置:
- C项目属性 -> linker -> General -> Additional Dependency Directories 添加对应MSVC版本的lib目录,根据编译平台追加
\x86或\x64后缀 - C项目属性 -> linker -> General -> Additional Dependency Directories 添加Fortran静态库编译输出的文件目录
- C项目属性 -> linker -> Input 中添加对应Fortran静态库的.lib文件名
- C项目属性 -> linker -> General -> Additional Dependency Directories 添加对应MSVC版本的lib目录,根据编译平台追加
- 源代码中引入包含
extern "C"声明的头文件,直接调用对应Fortran子程序即可正常编译运行。
内容的提问来源于stack exchange,提问作者YS_Jin
相关产品推荐
相关产品推荐

