永发信息网

VC 2005 如何调用fortran 库函数

答案:2  悬赏:20  手机版
解决时间 2021-11-24 14:57
VC 2005 如何调用fortran 库函数
最佳答案
正好最近一个项目需要在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
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.
全部回答
VC 2005和Fortran混合编程借助于Fortran生成的DLL进行(采用C默认的传址方式进行函数参数传递)方法和实例:
1.Fortran
生成DLL
新建Fortran
DLL程序test1.f
添加如下代码:
! test1.f90

! FUNCTIONS/SUBROUTINES
exported from test1.dll:
! test1 -
subroutine
!示例没有返回值的子例程
subroutine
test1(a,b)
! Expose subroutine test1 to
users of this DLL

!DEC$ ATTRIBUTES
C,DLLEXPORT::test1
! Variables
! Body of
test1
integer a,b
integer sum
sum=a+b
return
end subroutine
test1
!示例有返回值的整数四则运算
!两数相加
function
add(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::add
integer
a,b,add
add=a+b
return
end
!两数相减
function
abstract(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::abstract
integer
a,b,abstract
abstract=a-b
return
end
!两数相乘
function
multiply(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::multiply
integer
a,b,multiply
multiply=a*b
return
end
!两数相除
(需要添加考虑被除数是否为0以及能否整除的判断)
function
divided(a,b)
implicit none
!DEC$ ATTRIBUTES
C,DLLEXPORT::divided
integer
a,b,divided
divided=a/b
return
end
编译后生成test1.dll,test1.obj等文件。其中这两个文件是我们在VC中调用所需要的。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
河大成考什么时候报名
flash as2.0 中if(a!=b!=c!=d!=e!=f!=g)正确
在pkpm3.1.6 版本上没有
昨晚武江交警查酒驾,又有多人被抓现行
宁夏银川兴泾镇火车装卸在哪呢
中国移动(商鞅路厢叶茶楼旁)地址有知道的么?
停车场(灌河路)(鹳河路东50米停车场)地址在哪
喷泉模型的优点缺点
前两天明明淘宝店一款产品被查虚假交易违规的
从仙葫人人超巿坐几路公交车去火车站
5(2Ⅹ一3Ⅹ)十4(3一2Ⅹ)求结果
木落雁南渡 北风江上寒什么季节
中国移动(机场路田园汇旁)地址在什么地方,想
求这张望月椎那的超清图和出处
济宁运合车检在哪里?
推荐资讯
“蛛丝马迹”猜个动物?
EXCEL宏Private Sub Worksheet_Change(ByVal
我九八年一月,现年多少周岁多少虚岁
能用在微波炉里的塑料碗和瓷碗 用哪种碗对身
求教大神,中财怎么复习
空调制冷的四大部件?
笔记本电脑键盘下两排失灵
电气设计时如何选择GGD或GCK配电柜
拼多多如果没有人参团你的钱还还给你吗
黑客协会创始人花无涯,处在一个 提倡共 享的
从哈尔滨自驾游到牡丹江柴河小九寨怎么走
电话手表后面的条形码没了怎么办
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?