通过引用从C到Delphi DLL传递双数组

时间:2014-04-25 13:38:12

标签: c arrays delphi dll

对于我们的Delphi(XE5)应用程序,我们正在开发API。为了将来自Delphi DLL函数的数据与主程序(基于C的;(控制台)C或C ++代码应用程序或Matlab和Simulink)进行通信,调用者分配的数组需要由DLL填充双精度数。 / p>

据我所知,开放数组(Delphi特定)对于此目的来说不是很方便,因为它们包含您必须在C中模仿的其他数据。相反,我计划使用指针算法(请参阅dll函数:{{1}通过直接指向正确的地址。我的问题是,这是软件开发人员如何做到这一点。

下面包含一个演示(完整来源)。

DLL(在DXE5中制作):

inc(APDouble)

C代码调用者(在C ++ builder XE4中制作):

library PDA;

uses
  System.StrUtils,
  System.SysUtils,
  Vcl.Dialogs;

{$R *.res}

function ShowArrayContents( APDouble: PDouble;
                            size: Integer): integer; cdecl; export;
var
  i: Integer;
begin
  Result := 0;
  for i := 0 to size-1 do
  begin
    // Show value!
    MessageDlg(Format('%p -> %p -> %f', [@APDouble, APDouble, APDouble^]), mtWarning, [mbOK], 0);
    Inc(APDouble);
  end;
end;

exports
  ShowArrayContents;

begin

end.

1 个答案:

答案 0 :(得分:4)

您的代码运行正常,但正如您所看到的那样,它很尴尬。对于像这样的互操作,我会咬紧牙关并使用$POINTERMATH指令。这允许您将指针视为数组,就像在C或C ++中一样。例如:

{$POINTERMATH ON}
function GetSum(arr: PDouble; len: Integer): Double; cdecl; 
var
  i: Integer;
begin
  Result := 0.0;
  for i := 0 to len-1 do
    Result := Result + arr[i];
end;

另一种选择是复制到本机Delphi阵列并将其用于后续处理。显然这涉及到副本,但有时候实际上你想要的是副本。在这种情况下,你可以这样做:

var
  x: TArray<Double>;
....
SetLength(x, len);
Move(arr^, Pointer(x)^, len*SizeOf(arr^));

或者,如果您不喜欢使用Move,那么这是一个很好的旧循环:

{$POINTERMATH ON}
var
  i: Integer;
  x: TArray<Double>;
....
SetLength(x, len);
for i := 0 to len-1 do
  x[i] := arr[i];