马上注册,学习空分知识,结交更多空分大神!
您需要 登录 才可以下载或查看,没有账号?加入空分之家
x
FORTRAN语言动态链接库的使用及混合编译 转载自网上搜索到的一篇介绍FORTRAN动态链接库的资料——《Fortran语言的动态链接库的开发及应用》,同上海汽轮机期刊中《水和水蒸汽热力性质动态链接库的开发及在汽轮机中的应用》一文一致。仅供参考。 1 引言6 j# E j# U# S; X/ k% {
由于FORTRAN在开发图形界面、可视计算、面对对象、事件驱动、数据库应用方面存在局限性,如果我们利用其它语言来重写,将费时费力,同时又损失了FORTRAN语言在科学计算上的优越性。经过努力,笔者寻求到一种折衷的方法:利用Microsoft Fortran PowerStation 4.0将FORTRAN源代码编译为动态链接库,然后用其它语言建立应用程序的项目文件,在适当的时候调用该动态链接库。这样就把DOS环境中的软件包括移植到Windows环境,使问题得以圆满解决。) H8 L8 r( ?( ~; K& |
以下以最常用的子例程PT为例来说明动态链接库的建立和在各种流行程序语言中的调用方法。6 \% P+ M2 ^4 V9 J: _
% w, e% f4 Z' z1 z+ L
2 基于Fortran语言的动态链接库的建立
! z9 ~# \) }+ b. l! s) ]* M2.1 建立动态链接库的项目
$ w! U" ^8 s: n# [& Y' i( N在Fortran PowerStation开发环境中,建立动态链接库的项目文件(IFCSW.MDP)。2 S( H" E, c) Q% O
2.2 编写动态链接库的源代码
( H6 t7 T6 ?; D" \8 {+ B- y编写动态链接库的源代码文件(IFCSW.F90),并将源代码文件插入到动态链接库的项目文件中。( i9 o, ^1 s& a' [; E" L+ v
在动态链接库源代码(IFCSW.F90)中子例程PT的定义为
$ z; X, P" G5 xSubroutine PT(P,T,H,S,V,X,R)
0 d' H q0 ` q n!MS$Attributes Stdcall , Dllexport , Alias : ’PT’ :: PT
5 m6 L; |* J" |9 p( `4 ]!MS$Attributes Value :: P,T- T( z* z, Y# J
!MS$Attributes Reference :: H,S,V,X,R
) u; Y6 Y3 P; \: _- UReal(4) P,T,H,S,V,X
& s3 M J' H3 {. |+ a# X( nInteger(2) R
" n& s1 P3 L& C- S- A…………
* D/ m- v7 e" d. REnd Subroutine. W# F2 `4 x" `- m0 G1 ?
+ R3 g& `6 r' b8 l# s- p其中:P为压力,T为温度,H为比焓,S为比熵,V为比容,X为干度,R为所处的区间;如果调用前已知所处的区间,可直接给R赋区间号后再调用子例程,可避免区间判断而加快调用速度。当所处的区间未知或不确定时,由子例程内部进行区间判断后,针对不同区间再调用不同的其它例程,并将所处区间号传回。
. d3 r9 _# ^+ X' s- @6 |4 `: Q由于编译后动态链接库中命名方式的差异,为避免在VC++中隐式加载该DLL时产生连接错误,则专为VC++定义如下的子例程(仅供VC++使用),即不要使用命名别名的Alias语句:
7 D6 E/ H6 Y. j$ nSubroutine PTVC(P,T,H,S,V,X,R), n9 G3 o* ]/ |& q: \; w
!MS$Attributes Stdcall , Dllexport :: PTVC
. Q j" N% \4 Y" T5 a!MS$Attributes Value :: P,T
2 C0 X7 ^' Q0 i2 A4 G: g- q8 v!MS$Attributes Reference :: H,S,V,X,R! s% Y7 D& s/ t+ u: V2 m' }9 @
Real(4) P,T,H,S,V,X
: l5 b+ n4 T% l* q+ D/ {- g7 G3 [Integer(2) R
+ R& R( U& S7 d0 @% r* ~…………
9 {( B2 `: H8 p: U& q' T# oEnd Subroutine
3 f$ K9 O1 o6 z2 W& n9 v* U+ {
# H8 \5 b5 p% }2.3 创建动态链接库
8 Y5 k5 P7 i, b8 ?9 T对动态链接库的项目文件进行编译连接,获得动态链接库(IFCSW.DLL)和接入库(IFCSW.LIB,该接入库通常用于隐性加载动态链接库,且只能用于Microsoft的开发语言,对于其它公司的产品,需利用专用程序生成对应的接入库)。: F3 c8 E5 Q3 W2 f
/ x4 ~, t2 m% T7 G% S3 动态链接库的使用
' t. A' o4 |( G( e* r2 k0 t一旦生成了动态链接库,就可以在各种编程语言环境中调用该动态链接库中的各种子程序或子例程。
* Y5 l' \5 j- U动态链接库有隐式和显式两种装载方式,各有优缺点。采用隐式比显式友好,需要较少的编码,装载快速、可靠,但缺乏控制,影响动态使用,资源使用不经济;采用显式则正好相反。# v4 j' X5 H: T/ [$ M0 o
采用隐式通常需要接入库和函数申明。
, L5 O4 l4 l: {采用显式则应遵循以下步骤:. L* w L! ], |9 L9 j
(1) 创建一个函数指针,其指针类型与要调用的DLL引出函数相吻合。( a$ D5 { I( z# \+ K2 j. V6 _+ _
(2) 通过Win32 API函数LoadLibrary()显式地调用DLL,此函数返回DLL的实例句柄。
9 ]7 y8 p* s1 A) P9 R, o" s(3) 通过Win32 API函数GetProAddress()获得要调用的DLL的函数地址,把结果赋予自定义函数指针类型的指针。
& a) ?& e" e" N/ F3 `(4) 使用函数指针来调用DLL中函数。# ?% l4 c$ n' s) K3 k
(5) 调用完成后,通过Win32 API函数FreeLibrary()释放DLL。
+ b& Y- \4 {9 u+ X. r" ]( S, Z& C2 K6 @
实际使用中可将隐式和显式两者结合使用,采用混合模式。5 Y! S0 P5 r5 t* z8 }. N
8 p) M4 Z: z6 ~
3.1 在MS Fortran PowerStation 4.0中调用
* Y& B3 g# o5 v① 隐式调用
) e% R8 `# \ N+ ]! ]# |; M# t# r将接入库(IFCSW.LIB)包含到项目文件中,另在源文件的开始部分加入以下的声明语句 l6 {7 Z2 q9 I- q2 S( ?) L! Z4 v
Interface7 z! g6 G8 f! `2 o7 d
Subroutine PT(P,T,H,S,V,X,R)2 s% j4 V! }& v% E' Q
!MS$Attributes Stdcall , Dllimport , Alias : ’PT’ :: PT; S" d! f; h0 h$ }" j
Real(4) P,T,H,S,V,X
5 {. U0 G- L/ L U+ F4 ~Integer(2) R
V5 V3 G: W* a4 \) p* g. O!MS$Attributes Value :: P,T
# y$ N0 k2 t" W!MS$Attributes Reference :: H,S,V,X,R
* d0 P) m6 { h' Q) a- c5 }- Y, bEnd Subroutine. g+ Z* P1 @0 u! W* t9 @
End Interface
5 S5 F& R0 z2 L4 d0 _3 f此后,在需要的地方可用以下语句调用
: g" ^1 z) |" @. }Call PT(P,T,H,S,V,X,R)4 R: h) f2 z* t+ P1 I( ^
, Z. r7 b6 F; h* A4 e7 E; k
② 显式调用2 K0 u4 \) y, \) t' j" `+ n
动态装载首先要用LoadLibrary函数将动态链接库装入;然后用GetProcAddress函数获取动态链接库中要调用的函数或过程的地址;由于Fortran 90没有提供函数指针,不能直接用地址进行函数的调用,通过编写一个用函数名或过程名作参数的子程序CallProc来解决;将函数名或过程名作为参数传递时,实际传递的是四字节的函数或过程的入口地址,CallProc子程序接收该地址后,根据所声明的函数接口,以正确的方式对函数或过程进行调用;动态链接库使用完后,要及时用FreeLibrary函数释放动态链接库。2 `2 N' ?. a: [5 I4 ^+ R
Subroutine CallProc(Pn,P,T,H,S,V,X,R)! i: I) L; a" e% i1 x; g
Interface
3 Z) ~+ O- N1 _: ?Subroutine Pn(P,T,H,S,V,X,R)
6 N+ ^1 w' O K1 ^1 \; L6 Y1 z!MS$Attributes Stdcall , Dllimport :: Pn' y' I, m" i3 J& d4 K
Real(4) P,T,H,S,V,X
: M ]( O% B/ Z" }9 q) kInteger(2) R
( t6 {7 |" Z+ N6 q5 e7 N( _3 T!MS$Attributes Value :: P,T
1 m/ A& Q, L' K- P" q9 Q9 a!MS$Attributes Reference :: H,S,V,X,R
/ o7 u; F1 @5 ~7 L, D! l! mEnd Interface" o8 N; ~$ D5 t; T' u
Real(4) P,T,H,S,V,X
) R% H! a: A: Z8 _) Y ^7 U1 e! k/ vInteger(2) R
" S2 C! C* }) o! w( ~9 T- U) _Call Pn(P,T,H,S,V,X,R)
3 N+ g* `$ ~( lEnd Subroutine" c) F Y% h/ p# u) X# k9 l
* K4 s! n8 y) C3 l ]! d$ QCallProc(PT, P,T,H,S,V,X,R)$ `! t& L* I3 f# \
! Z" g! ]! Y* n# a7 E3.2 在Visual Basic和Visual Basic Application中调用1 m" L- [+ H P9 e- Q0 g$ \! M( s$ C
VB和VBA中由于显式加载过于繁琐,通常不使用,以下仅介绍隐式加载。7 ~9 y- _" |% L& x a# l- H/ X
VB和VBA中隐式加载不需要接入库,只需在模块代码的声明部分增加Declare语句,声明需调用的函数在外部动态链接库中。' \* c0 O1 D. y
Decalre Sub PT Lib “IFCSW.DLL” (ByVal P as Double , ByVal T as Double , ByRef H as Double , ByRef S as Double , ByRef V as Double , ByRef X as Double , ByRef R as Integer)
8 G) N8 V6 d6 A$ W& }# d; _, \而后,即可在任何需要的地方用以下语句调用子程序PT。$ x" T: b' M5 c* Z: Y
CALL PT(P,T,H,S,V,X,R)
0 G, `. o; |, N" M; v
8 w5 c+ p/ F c3 Y0 A3.3 在Delphi(Visual Pascal)中调用9 q; S0 K7 X1 C4 n4 v& K @! h
|