【发布时间】:2020-12-20 14:29:25
【问题描述】:
我正在尝试在 DLL 中编译一些非常古老的 Fortran 程序,以便能够在 Delphi 中使用它们。虽然 Fortran 代码不是很大(750-800 行),但它的结构非常复杂,有几十个 GOTO 命令,翻译也不是很容易(我尝试了一些有用的代码,但我失败了)。 虽然我是 Fortran 新手,调用 DLL 的经验也不是很丰富,但我逐渐克服了所有困难,但其中之一就是能够调用具有多个动态数组的 Fortran 子程序。这是我创建的一个简单示例:
SUBROUTINE MYSUB1( NoEquations, INTARR1 )
!DEC$ ATTRIBUTES DLLEXPORT::MYSUB1
!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'MYSUB1' :: MYSUB1
C
C***************************************************************
C
INTEGER NoEquations, I
INTEGER INTARR1(*)
C
C***************************************************************
C
DO 100, I=1,NoEquations
INTARR1(I) = I
100 CONTINUE
RETURN
C
END
SUBROUTINE MYSUB2( NoEquations, INTARR1, INTARR2 )
!DEC$ ATTRIBUTES DLLEXPORT::MYSUB2
!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'MYSUB2' :: MYSUB2
C
C***************************************************************
C
INTEGER NoEquations, I
INTEGER INTARR1(*)
INTEGER INTARR2(*)
C
C***************************************************************
C
DO 100, I=1,NoEquations
INTARR2(I) = INTARR1(I)
100 CONTINUE
RETURN
C
END
我用 mingw-w64 用以下命令编译 Fortran 代码:
gfortran -shared -mrtd -fno-underscoring -o simple.dll simple.f
我在 Delphi 中声明该过程:
procedure mysub1(var NoEquations: integer; var INTARR1 : array of integer); stdcall; external 'simple.dll';
procedure mysub2(var NoEquations: integer; var INTARR1,INTARR2: array of integer); stdcall; external 'simple.dll';
Delphi proram 可以正确编译,但是当我运行它时,mysub1 可以正常工作并更新 INTARR1,但是 mysub2 给了我访问冲突。显然,第二个动态数组使编译器感到困惑,但我不知道如何使其理解。 提前致谢
【问题讨论】:
-
不要使用开放数组参数。使用指向数组元素类型的指针。开放数组参数有额外的隐含参数来指定长度。
-
谢谢!你的意思是一个大的整数数组和指向这个数组的指针?
-
@Stelios Antoniou 问题不在两个数组参数中,所有声明都是错误的,第一个过程意外地正常工作。
INTARR1,INTARR2: PInteger可能会有所帮助。还有内存分配呢? -
@David Heffernan。有没有关于如何拨打电话的例子?我需要同时更改 Delphi 和 Fortran 代码吗?
-
这两种方式的工作似乎一样多。 1000 行的任何内容并不难翻译,而且像 fortran 这样冗长的东西更是如此。我在这里压倒性的偏好是重写。 “这太难了”似乎是坚持传统复杂性海锚的微不足道的理由。我怀疑这 1000 行可能会在 Delphi 中被重写为一半或更小的大小,同时也变得更加清晰和易于阅读。您最终可能还会了解代码在其末尾的作用——我们可以推断您目前不了解。