已知: 主程序的所有C++源代码
静态库的所有Fortran源代码
工具: Compiler: MS Visual C++ 2010(x86)
Compiler: Intel Visual Fortran 2011(x86) ,即IVF 12
IDE: Microsoft Visual Studio 2010
问题: C++代码中需要调用Fortran子程序,由于Visual Studio已不含Fortran编译器,所以无法混合编译,只有先将Fortran代码编译成静态库,再从C++代码中调用。问题是Fortran子程序可以顺利编译成静态库(.lib文件),但在C++工程中却不能调用,总是提示“无法解析的外部符号 _XXX,该符号在函数 _XX 中被引用”。
刚遇到这个问题时,百度Google一下,发现仅有的一点参考信息来自
http://bbs.sjtu.edu.cn/bbstcon?board=VS&reid=1292155137
但是,很遗憾,按照这位中国哥哥的提示,还是不行,仍然提示“无法解析的外部符号 _XXX,该符号在函数 _XX 中被引用”。于是继续Google,发现老外专家的回答,硬着头皮看完,OK,问题解决,现总结如下:
1.针对Fortran子程序 Subroutine ffun 的声明,一般都是按照如下格式声明
extern "C" void __stdcall FFUN(int& i); //FFUN要大写(重要)
然后按照 FFUN(a)使用,这也是彭国伦Fortran95程序设计书中教的方法,这种操作在VC6.0中可以正常使用,但是在VS2010中却不行,在VS2010中声明为__stdcall的话,FFUN会被编译成 FFUN@4 ,而 Fortran 中被编译成FFUN,所以仍然提示“无法解析的外部符号FFUN@4,该符号在函数 _XX 中被引用”,如果声明为__cdecl或直接省略这部分声明的话,就不存在这个问题,所以VS2010中不能再将 Fortran 子程序声明为 __stdcall,而是声明为
extern "C" void FFUN(int *a);
2.Different runtime library specified for C and Fortran project - these must be consistent
You can change the Runtime Library settings in BOTH projects to be "Multithreaded" (not Multithreaded DLL) and it should do what you want.
什么意思?编译Fortran静态库时,要设置工程->属性->c/c++->代码生成->运行库为多线程调试(Debug下),而不是多线程调试DLL。同时,在调用Fortran静态库的C++工程中,也要做同样的设置才行。
3.libifcoremt.lib explicitly listed as an additional dependency in C project - remove
msvcrt.lib listed as "ignore" in C project - remove
编译时有时会出现“无法打开文件ifconsol.lib ”等一些情况,这时需要添加ivf库路径和附加依赖项解决。有时还会提示库冲突,中国哥哥的解决方法是从项目中排除默认的库,可是如果都做了“运行库为多线程调试”的设置,基本上不会出现这种问题,而且老外明确表示要去掉忽视的库(msvcrt.lib listed as "ignore" in C project - remove)。(In Visual Studio, go to Tools > Options > Projects > VC++ Directories. For "Library Files", add the full path to the Intel Fortran "Lib" folder.)
如此,基本上就解决了。注:本人也是摸索中学习,记录下来仅自己备忘,望大神勿喷。