通过与Fortran 的混合编译在C 中实现动态数组

时间:2022-10-23 06:09:34

通过与Fortran 的混合编译在C 中实现动态数组

摘要:动态数组在数据处理时有着独特的优势,Fortran语言数组功能强大并支持动态数组,而C语言不支持动态数组。利用Fortran与C/C++的混合编译思想,通过调用Fortran90例程的方法,在C中实现动态数组并给出了程序代码。

关键词:动态数组;Fortran;C/C++;混合编译;调用约定

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2013)18-4192-03

数组是处理大量数据时的有力助手。在不能够事先确定数组大小的情况下,为避免数据溢出或越界,就要足够大的数组。这种方法使用过度,会迟滞内存操作。故此,理想的数组能够动态确定大小,即程序运行中先向系统申请一个大数组,不使用时再将其内存空间释放掉。而动态数组很好地满足了这一要求。但C语言不支持动态数组,不能动态定义数组元素的数量。如何解决这一矛盾将是本文的着力点。

1 Fortran中的动态数组

Fortran90数组功能强大,执行程序时能够动态分配数组存储空间和实际大小,不使用时再将其内存释放还给系统;支持直接操作数组段、数组整体;支持逐个操作数组元素;支持面向数组操作的函数和构造块[1]。Fortran 90中运用动态数组需要三个步骤:

1)声明动态数组。明确数组的维数,不规定维的上、下界和大小(即延迟形状数组)。如:REAL,DIMENSION(:),ALLOCATABLE::X。

2)给动态数组分配内存。如:ALLOCATE(X(N))。

3)将分配的内存释放掉。如:DEALLOCATE(X)。

2 Fortran与C/C++的混合编译

在32位Windows系统下,同时安装Compaq Visual Fortran 6.x和Microsoft Visual C++ 6.0,则两者共享一个可视化开发环境(Microsoft Visual Studio 6.0)[1]。Fortran与C/C++任一种语言都可以作为主程序,调用另一种语言编写的例程。但两者在目标例程命名、堆栈管理以及参数传递方面的行为模式不完全一致,要协调其调用约定。

Fortran使用的调用约定有缺省约定(Default)、STDCALL约定和C约定。在Visual Fortran 6.x的编译器下,作用于例程参数和整个外部例程的属性不同,会影响堆栈管理、例程命名、参数传递。

2.1 堆栈管理

Fortran与C/C++间的例程调用是通过堆栈进行的。在缺省约定和STDCALL约定下,堆栈由被调用例程(Colleen)控制。在C约定下,堆栈由调用程序(Caller)控制,所以例程参数驻留在堆栈什么位置、占用多少字节等信息都是调用程序获知,该约定下传递参数的数量是可以变化的,是可选参数[2]。

2.2 例程命名

在编译生成的目标文件(.OBJ)中,标示符诸如全局变量、外部例程、模块等,在整个程序作用域内是独一无二的,共享于各个程序单元[3]。C对字母的大小写敏感,C++增加了特定的修饰,而Fortran忽略字母大小写,使得目标标示符在编译后发生变化。而命名约定,就是保持目标标示符在编译时一致性的命名规则。为保证链接成功,就要协调命名约定。

C++增加的修饰受特定系统影响,如将其去掉,就是在函数中添加C链接选项(extern “C”),则C++与C的命名约定相同。

协调Fortran与C/C++的例程命名分大写、小写和混合三种情况:

1)大写。Fortran是缺省约定,其目标外部例程名统一被转换为大写,那么在C/C++中须采用_stdcall约定,并用大写命名外部函数。

2)小写。Fortran是C约定或STDCALL约定,其目标外部例程名统一被转换为小写,那么在C/C++中须采用缺省约定_cdecl或_stdcall约定,并用小写命名外部函数。

3)大小写混合。C/C++的外部函数名是大小写混合形式,在Fortran中若要保持一致的形式,必须采用ALIAS属性来限定产生的目标例程名。

2.3参数传递

1)参数传递方式

Fortran参数传递方式取决于调用约定[4]。Default状态下,Fortran为引用传递;C或STDCALL约定状态下,数组参数为引用传递;单个参数为值传递。在调用约定之外,为忽略掉调用约定对参数传递的影响,可以规定参数拥有VALUE和REFERENCE传递属性[5]。在混合编程中,应通过VALUE和REFERENCE属性明确规定参数的传递方式,而不是依赖于调用约定。

C/C++参数传递方式不受调用约定影响。数组参数为引用传递;单个参数为值传递。单个参数可转换为引用方式传递,C中可选指针参数;C++中可选指针参数或引用参数。

2)数据类型的对应

要使Fortran和C/C++的混合编程获得成功,不仅要求对其调用约定、命名约定等进行协调,还要求保持数据类型相互一致。事实上,实型和整型是数值计算过程中经常运用到的,并且在两种语言中其数据类型有着很好的一致性,其对应关系如表1。

3 C中动态数组的实现实例

下面给出一个利用Fortran与C/C++的混合编译在C中实现动态数组的实例。该实例包含以一个外部例程,其功能是利用动态数组实现学生成绩及学生人数的输出。

具体实现过程如下:打开安装好的开发环境,Microsoft Visual C++ 6.0或Compaq Visual Fortran 6.x中的Developer Studio界面,点击new text file快捷按钮,保存为(.f90)文件,在其中编写Fortran外部例程。

代码如下:

SUBROUTINE PrintMarks(Students)

IMPLICIT NONE

!DEC$ ATTRIBUTES STDCALL,ALIAS:'_PrintMarks@4'::PrintMarks

!DEC$ ATTRIBUTES VALUE::Students

INTEGER(4) :: Students

REAL,ALLOCATABLE::Marks(:)

INTEGER K

WRITE(*,'(A)',ADVANCE='NO') 'How many student:'

READ*,Students

ALLOCATE(Marks(Students))

DO K=1, Students

PRINT*,'输入第',k,'个学生的成绩:'

READ*,Marks(K)

END DO

PRINT*,Marks

DEALLOCATE(Marks)

print*,Students

END SUBROUTINE

同理,再建立一个(.c)文件编写主程序,在C中调用Fortran例程。

主程序代码如下:

#include

void main()

{ void _stdcall PrintMarks(int Students);

int Students=0;

PrintMarks(Students); }

编写好程序代码后,以(.c)文件建立链接并生成活动的工作空间,将Fortran外部例程的文件添加到工作空间中,混合编译即可获得成功,得到正确的运行结果:通过C程序中调用Fortran例程在C中实现动态数组。

4 结论

通过C程序调用Fortran例程的混合编译方法,实现了C语言的动态数组功能,一定程度上弥补了C不支持动态数组的缺憾。此外,Fortran90其他的优势数组功能可否通过调用的方式增强C数组功能的不足,或许是可行的研究方向。

参考文献:

[1] 周振红.Fortran 90/95 高级程序设计[M].郑州:黄河水利出版社,2005.

[2] 任慧,周振红,张成才.Fortran与C/C++的混合编译[J].计算机工程与设计,2007(9):4096-4098.

[3] 毕苏萍,周振红,贺晓慧.Fortran90借用C++函数模板[J].郑州大学学报:工学版,2013(3):64-66.

[4] 周振红,王国宾,毕苏萍.Fortran与VB传递单一字符串的几种方式[J].郑州大学学报:工学版,2011(1):116-120.

[5] 周涛,郭占元,郭向荣.FORTRAN与C#混合编程在土木工程计算中的应用[J].山东交通学院学报,2009(3):80-85.

上一篇:基于UML 的DCS 数据库系统的建模与实现 下一篇:软件技术课程中智力三环游戏设计