C#与Fortran混编的一个例子

由于历史等原因,有许多数值计算相关的模型都是用Fortran写的。这些模型大多经过历史的考验,具有很高的应用价值。另一方面,现有的应用系统大多拥有用户界面,便于使用,例如C#写的WinForm程序。所以,将模型与界面结合起来,即C#与Fortran进行混编很有必要。

最近我也在做这方面的工作,看到有许多文献涉及这些问题:

混编中的各种问题这些文献中几乎都提到了,我就不再重复,况且我的实际工作中也没涉及所有问题。下面我提供一个简单的混编例子,其目的是将Fortran的Dll(SimpleFortran.dll)在C#的控制台中调用起来。当然,两者之间必须有中介,即经过封装。显然,封装是整个过程中相对有价值的部分。

先看原始的Fortran代码,即SimpleFortran.f90。代码拷贝自彭国伦的书中(p381):

其中有两个函数,一个子例程。分别为:根据半径计算圆面积(circle_area)、计算长度为10的数组之和(sum)、将小写字母变为大小(MakeLower)。将源代码生成为SimpleFortran.dll,但C#程序显然不能直接调用Fortran的Dll。所以必须进行封装,这就引出了封装代码,SimpleFortran.cs:

其中,通过DllImport特性将SimpleFortran.dll引入,并声明方法。值得注意的是,其方法签名和Fortran代码中的同名函数或子例程是不一致的,这是两种语言的运作机制造成的差异,也是混编中很重要的问题,具体差异可以参考前面列的文献。在程序实体中写封装方法,供外界调用,例如“F_MAKELOWER”,F表示实际调用的是Fortran代码,MAKEFLOWER为Fortran中的函数名。将这些代码封装为FortranFirstPackage.dll,供控制台调用即可。调用代码如下:

先实例一个SimpleFortran对象,然后通过对象的方法调用即可。其过程中看不出调用的是Fortran的代码痕迹(方法名当然例外),很符合C#的编程习惯,这也就达到了封装的目的。

最后,看一下结果:

当然,混编中的问题远不止这些,因为模型的复杂度远远超过这些例子。特别是参数传输方式的设计,既要符合调用方的习惯,又要符合被调用方的规范。如果是在分布式网络环境下,考虑的问题就更多了。

Leave a Comment

* are Required fields