陈彦瑾
(河海大学 水利水电学院,江苏 南京)
Fortran 语言是世界上最早出现的计算机高级编程语言,在科学和工程计算领域相比其他编程语言更具优势。即使在计算机语言发展到今天的多元时代,Fortran 语言仍在广泛使用[1-2]。因此,完善其使用方法或功能,还是有一定意义的。
王柯等[1]基于Fortran 语言,分析了粮堆温度、水分含量、储粮害虫增长量以及杀虫剂浓度衰减的变化。杨成坤等[2]研发地下及井中探测软件平台,其中很多模块由Fortran 语言编写。齐云飞、胡凡[3]基于Fortran与VB 混合编程建立了水库群联合优化调度系统。很多高校至今仍将Fortran 语言列为本科生教学主干课程[4]。
使用静态链接库对部分程序进行封装是常用的手段之一,使用很广泛。本文主要介绍在Fortran PowerStation 4.0 环境下建立静态链接库,利用主程序调用静态库的方法,并结合示例程序介绍该方法的使用。
首次建立静态链接库项目工作空间时,需要在Fortran Powerstation 4.0 环境下打开 Microsoft Developer Studio,执行File-New 命令,在弹出的新建(New)窗口中选择项目工作空间(Project Workspace),如图1 所示,点击OK 后在New Project Workspace 对话框中选择项目类型(Type)为Static Library(静态链接库),输入项目文件名称如Sub,软件默认的文件存储位置为“C:MSDEVProjects”,点击Creat 后会在Projects 目录(即文件夹,以下所谓“目录”均指文件夹)下生成名为Sub 的项目文件夹,Sub 目录内生成Sub.mak 文件。这时,静态链接库的项目工作空间已经建立完成,接下来就可以准备输入静态库程序代码。
图1 Fortran Powerstation 4.0 新建文件建立方法
执行File-New 命令,在新建文件对话框中选择Text File (或工具栏中选择New Source File),生成Text1 文件,文件类型保存(File-Save)为Sublib.for,然后输入程序代码。静态链接库的程序代码与一般子程序的编写规则完全一样。程序代码编写完成并存盘后,执行工具栏中Compile 命令 (或菜单栏Bulid-Compile Sublib.for)编译Fortran 程序,此时弹窗提示“This File is not included in the Project”,确认添加即可。
Fortran Powerstation 4.0 软件默认的编译模式是Win32 Debug 模式,信息栏中提示编译正常通过之后,会在Sub 目录下建立Debug 文件夹并生成Sublib.obj 文件。执行工具栏中Build 命令 (或菜单栏Bulid-Bulid Sublib.lib)建立链接库,在Debug 目录下生成Sub.lib 文件,此文件即为新建立的静态链接库文件。由于链接库文件一般不需要经常修改,只要声明程序接入点便可使用,因此可以在编译程序时选择Release 模式,以提高执行效率。此时会对应生成Release 目录及相应的obj 和lib 文件。
如果用来做静态链接库的程序代码已存在,即Sublib.for 文件已有,就只需要将其添加到静态库项目工作空间中去。建立好的项目工作空间(即Projecct Workspace-Static Library)后,执行菜单栏Insert-Files into Project 命令,在弹出的对话框中找到Sublib.for 程序代码,点击OK。执行Compile 和Bulid 命令后,会对应在Sub 文件夹的debug 或Release 目录生成Sublib.obj 和Sub.lib 文件。
主程序代码中不包含链接库代码,主程序调用时只要知道链接库中子程序名称或模块名称即可。假定此时静态库Sub.lib 文件已经生成,主程序也已经完成。剩下的工作就是如何运行主程序,并调用静态库,完成相应计算任务。
在主程序代码Program Main 后添加语句“!MS$OBJCOMMENT LIB:'Sub.lib'”可以实现静态库的添加。其中“!”在此处是伪注释的用法,用来声明将Sub.lib链接库文件添加到主程序中。该行在编译的过程中并不是注释语句,可以与编译器进行通讯,不可缺失。
当主程序调用(静态库中的)子程序,如Sub1 时,只需在主程序代码中需要调用Sub1 的位置使用Call sub1 语句来声明调用子程序,其中Sub1 为子程序名。当然,需要注意的是需将名为Sub.lib 的链接库文件存放到主程序所在的目录下连接时才可以搜索到。此时,便可打开主程序,如A.for,执行Bulid 命令,可以看到编译连接成功,即可执行Bulid Execute A.exe,主程序会调用静态库中子程序Sub1 完成计算。
一些程序封装为模块使用起来可能更方便,只要在主程序代码中使用Use ModD 语句就可调用模块中相应函数及子程序,其中ModD 为模块名。将Module模块编译为静态库时,同样要先建立Static Library 类型的名为Module 项目工作空间。含Module 模块的静态库程序代码Mod.for 结构如下:
Module ModD
Contains
……
End Subroutine
End Module
中间省略的代码为子程序代码,需要指出此时子程序结束语句应当用End Subroutine 而不能采用省略Subroutine 的End 形式。依次执行Compile 和Bulid 命令,在Debug 或Release 目录下会生成modd.mod、Mod.obj 文件和Module.lib 文件。扩展名mod 文件为模块,lib 文件为静态库文件。
主程序接入含Module 模块的静态库时首先使用语句“!MS$ OBJCOMMENT LIB: 'Module.lib'”添加静态库,使用模块时需要用Use ModD 语句声明使用,使用Call sub 命令可调用相应的子程序。此处需要注意的是,应将modd.mod 模块文件和Module.lib 链接库文件同时存放到主程序的目录下。
链接库可以嵌套使用,因此在将Module 模块编译为链接库时也可调用其他静态库。
由于不同问题的复杂性,往往要对程序进行不断改进来适应更多的情况,因此就需要对已经生成的静态链接库进行不定期的更新和维护。
首先确认Sub.mdp 及Sub.mak 文件存在,执行菜单栏File-Open Workspace 命令,在Open Project Workspace 窗口中打开sub.mdp 文件,在项目空间树形菜单中双击Sublib.for 可修改程序代码文件,修改存盘后执行Bulid 命令就可以在Debug 或Release 目录下建立新的Sub.Lib 文件。
需要指出,静态库进行更新维护后,重新生成了Sub.lib 文件。需将此新静态库文件存放到主程序目录下,而且主程序在使用前必须重新编译连接生成新的A.exe。这是因为旧的可执行程序A.exe 是将更新前的链接库程序编译到了A.exe 中,如果只重新链接或只执行旧的可执行程序,则调用的链接库仍为上次编译的更新前的内容,因此,必须重新编译连接主程序代码生成新的A.exe 方可使用新静态库。
本节结合Fortran 语言编写的有限元计算程序中一部分功能,详细介绍使用静态链接库的具体步骤。
示例子程序的功能为:通过读取线弹性材料的弹性常数弹性模量E 和泊松比ν,形成有限元法中使用的物理方程的弹性矩阵D,计算公式如式(1)。
矩阵D 完全由E 和ν 决定,可以把由E 和ν形成D 的过程建立为静态库,主程序只要提供材料的E 和ν 值,通过调用静态库中对应的子程序SubD 即可得到材料弹性矩阵D。子程序代码见表1。
表1 材料弹性矩阵D 子程序
建立名为Sub 项目类型为Static Library 的项目文件目录,添加链接库程序代码Sublib.for,以Win32 Release 模式执行Compile 及Bulid 命令,编译连接程序后会在Sub 目录下生成Sub.mak,sub.mdp 文件,Release 目录下生成Sub.lib、Sublib.obj 文件,其中Sub.lib 即是所需要的静态库文件,主程序调用时只要在程序代码中声明程序接入点即可调用链接库中子程序。
在主程序中使用语句“!MS$ OBJCOMMENT LIB:'Sub.lib'”调用静态库,使用Call SubD 语句调用静态库中相应子程序。主程序代码如表2 所示。
表2 材料弹性矩阵D 子程序
用Microsoft Developer Studio 打开主程序代码Main.for 文件,确认之前项目空间关闭后,执行Compile 和Bulid 命令,编译链接主程序代码。注意,此处需将Sub 文件夹Release 目录下的Sub.lib 文件存放到当前主程序目录下,主程序调用链接库时才可搜索到。当链接库中含有Module 模块时,项目空间建立方法,需要将Modd.mod 模块和Module.lib 链接库文件一并放到主程序目录下方可链接成功。本例输入文件E-v.dat 数据为第一行2;第二行为50000.0,0.30;第三行为100000.0,0.25。
执行Bulid-Bulid Execute Main.exe,输出上述两种材料的6*6 的弹性矩阵D,说明主程序调用Sub.lib链接库的SubD 子程序形成矩阵D 是成功的。主程序得到的矩阵D 结果如下:
本文详细的介绍了在Fortran Powerstation 4.0 环境下建立静态链接库并在主程序中调用静态库里子程序的使用方法,主要结论如下:
(1) 本文介绍的静态链接库的建立和使用十分方便,可方便地用于大型程序中通用子程序的封装,具有较强的实用价值。
(2) 静态链接库可以包含多个子程序及Module模块,静态库之间也可以嵌套使用,主程序亦可以同时调用多个静态库,其适用性很强。
(3) Fortran Powerstation4.0 环境下使用静态链接库方法十分简单,只需在主程序代码中添加一行语句,编译连接主程序就可以使用。