我将其发布为答案,因为评论有点过于有限,无法表达这一点。
这个答案试图解释 FORTRAN 和 Delphi 中数组和记录的内存布局的差异,并修改了Todd Grigsby的答案和Remy Lebeau的答案(我都赞成)。
FORTRAN 和其他一些以计算为中心的语言按列主要顺序存储嵌套数组。Delphi 和许多其他语言都使用行大命令。
从内存的角度来看,一条记录只不过是一个字段数组,它们:
对于计算密集型操作,当您的算法有利于列时,存储嵌套数组列的主要顺序是有意义的。与行主要订单相同。因此,在循环中,您需要将索引的顺序与存储的顺序相匹配。
鉴于 FORTRAN 中的此记录和数组定义:
TYPE WallInfo
CHARACTER(len=40) :: Name
REAL :: Azimuth
REAL :: Tilt
REAL :: Area
REAL :: Height
END TYPE WallInfo
TYPE(WallInfo), ALLOCATABLE, DIMENSION(:) :: Wall
以及 Delphi 中的功能等效定义:
type
WallInfo = record
Name: array[0..39] of Char;
Azimuth: Real;
Tilt: Real;
Area: Real;
Height: Real;
end;
var
Wall: array of WallInfo;
和一个由 3 个 WallInfo 元素组成的数组,这就是内存布局的外观(它们都是连续的内存区域,我将它们分成几行以保持可读性):
在 FORTRAN 中:
Name[0,0]...Name[0,39], Name[1,0]...Name[1,39], Name[2,0]...Name[2,39],
Azimuth[0], Azimuth[1], Azimuth[2],
Tilt[0], Tilt[1], Tilt[2],
Area[0], Area[1], Area[2],
Height[0], Height[1], Height[2],
在德尔福:
Name[0,0]...Name[0,39], Azimuth[0], Tilt[0], Area[0], Height[0],
Name[1,0]...Name[1,39], Azimuth[1], Tilt[1], Area[1], Height[1],
Name[2,0]...Name[2,39], Azimuth[2], Tilt[2], Area[2], Height[2],
所以这个 FORTRAN 电话:
CALL HeatFlow(Wall%Area, Wall%Azimuth)
只会将指向 Area[0] 和 Azimuth[0] 内存位置的指针以及这些内存区域的长度传递给函数。
在 Delphi 中,这是不可能的,所以你必须
- 构建新的区域和方位角阵列
- 从名为 Wall 的 WallInfo 记录实例数组中的信息中复制它们
- 将它们发送到函数
- 如果这些是 var 参数:将两个数组中的更改复制回 Wall
Todd Grigsby和Remy Lebeau使用直接的 Delphi 代码或 Delphi 记录 RTTI 在他们的答案中展示了前三个步骤。
第 4 步的工作方式类似。
两种解决方案都使用 Delphi 2009 中引入的泛型。
在 Delphi 2010 之前,记录上的 RTTI 非常少),因此您得到了两个答案的正确 Delphi 版本。
注意(再次):将您的算法从 FORTRAN 转换为 Delphi 时,请确保注意数组中的循环和其他索引,因为列/行的主要变化。