如何找出Fortran程序中使用的库
我把自己的Fortran程序做成了动态链接库,但是在不装Fortran的电脑上无法运行,是少了库文件,我怎么才能找到我的程序用到的库,并且把库拿出来呢?...
我把自己的Fortran程序做成了动态链接库,但是在不装Fortran的电脑上无法运行,是少了库文件,我怎么才能找到我的程序用到的库,并且把库拿出来呢?
展开
1个回答
展开全部
正好最近一个项目需要在C/C++程序中调用Fortran写的DLL, 有一些心得记录下来.
我用的C/C++集成环境是VC8(.Net 2005), Fortran编译用了Intel Visual Fortran Compiler 9.1, 在WindowsXP SP2上进行开发.
调试的时候, Dependency Walker这个软件很有用, 能直接看到编译出来的DLL中的信息.
首先写了一个fortranlib.dll, 很简单, 只有一个函数, 代码如下:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
然后写了一个callfortran.exe, 代码如下:
#include <iostream>
extern "C" double __stdcall testfunc(double x, double y);
int main(int argc, char* argv[])
{
double a = 2.0;
double b = 1.0;
double c;
c = testfunc(a, b);
std::cout << b << std::endl;
return 0;
}
需要将fortranlib.lib作为callfortran.exe的additional dependency才能编译通过, 然后就可以work了.
如果两边都采用C的calling convention, 也可以编译通过且正确运行. 修改如下:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, C::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __cdecl testfunc(double x, double y);
另外, 如果要采用REFERENCE型的传参规则, 以stdcall为例, 应改为:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES REFERENCE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __stdcall testfunc(double* x, double* y);
要注意的几点:
1. Fortran忽略大小写, 如果代码中函数名含大写, 那么在编译出来的库中, 函数名称全部都被转成小写了(用Dependency Walker可以看到). 而C/C++是区分大小写的, 所以在C/C++中声明extern的函数时必须用小写的名字, 除非fortran函数被"!DEC$ ATTRIBUTE ALIAS"指令强制化名为含大写字母的名称.
2. Fortran中的几个涉及到Calling Convention和传参规则的"!DEC$"指令, 最好都显式的写出来. 因为不同的编译器以及在不同的操作系统上, 默认的编译行为都很可能不一样. 采用默认行为容易遇到一些原因很难查清的问题. C/C++也一样, 最好显式的写清楚是__cdecl还是__stdcall.
我用的C/C++集成环境是VC8(.Net 2005), Fortran编译用了Intel Visual Fortran Compiler 9.1, 在WindowsXP SP2上进行开发.
调试的时候, Dependency Walker这个软件很有用, 能直接看到编译出来的DLL中的信息.
首先写了一个fortranlib.dll, 很简单, 只有一个函数, 代码如下:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
然后写了一个callfortran.exe, 代码如下:
#include <iostream>
extern "C" double __stdcall testfunc(double x, double y);
int main(int argc, char* argv[])
{
double a = 2.0;
double b = 1.0;
double c;
c = testfunc(a, b);
std::cout << b << std::endl;
return 0;
}
需要将fortranlib.lib作为callfortran.exe的additional dependency才能编译通过, 然后就可以work了.
如果两边都采用C的calling convention, 也可以编译通过且正确运行. 修改如下:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, C::testfunc
!DEC$ ATTRIBUTES VALUE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __cdecl testfunc(double x, double y);
另外, 如果要采用REFERENCE型的传参规则, 以stdcall为例, 应改为:
testfunc函数代码:
double precision function testfunc(x, y)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL::testfunc
!DEC$ ATTRIBUTES REFERENCE::x, y
implicit none
double precision x, y
testfunc = x - y
return
end function testfunc
并且callfortran.exe中函数引入声明改为:
extern "C" double __stdcall testfunc(double* x, double* y);
要注意的几点:
1. Fortran忽略大小写, 如果代码中函数名含大写, 那么在编译出来的库中, 函数名称全部都被转成小写了(用Dependency Walker可以看到). 而C/C++是区分大小写的, 所以在C/C++中声明extern的函数时必须用小写的名字, 除非fortran函数被"!DEC$ ATTRIBUTE ALIAS"指令强制化名为含大写字母的名称.
2. Fortran中的几个涉及到Calling Convention和传参规则的"!DEC$"指令, 最好都显式的写出来. 因为不同的编译器以及在不同的操作系统上, 默认的编译行为都很可能不一样. 采用默认行为容易遇到一些原因很难查清的问题. C/C++也一样, 最好显式的写清楚是__cdecl还是__stdcall.
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询