You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi中调用C++ DLL的二维DoubleArray结构

Delphi调用LabVIEW风格DLL并访问嵌套指针数据

DLL的C头文件定义

typedef struct {
    int32_t dimSizes[2];
    double NumericControl[1];
} DoubleArrayBase;
typedef DoubleArrayBase **DoubleArray;
    
void __stdcall ReadTERFCorrectedData(char FilepathString[], 
    int32_t ArrayLengths[], DoubleArray *AmplitudeData, 
    DoubleArray *FrequencyData, int32_t len);

DoubleArray __cdecl AllocateDoubleArray (int32 *dimSizeArr);
MgErr __cdecl ResizeDoubleArray (DoubleArray *hdlPtr, int32 *dimSizeArr);
MgErr __cdecl DeAllocateDoubleArray (DoubleArray *hdlPtr);

现有代码问题

你编写的Delphi声明及调用代码存在调用约定不匹配、参数类型错误等问题,导致无法正确访问数据:

错误的Delphi声明

type
  PDoubleArray = ^DoubleArray;
  DoubleArray = ^PDoubleArrayBase;
  PDoubleArrayBase = ^DoubleArrayBase;
  DoubleArrayBase = packed record
    dimSizes: array[0..1] of Int32;
    NumericControl: array[0..0] of Double;
  end;

  procedure ReadTERFCorrectedData(FilepathString: PAnsiChar;
                                  var ArrayLengths: Int32; AmplitudeData, FrequencyData: PDoubleArray;
                                  len: Int32);stdcall; external DLLDirectory;
  function AllocateDoubleArray (SizeArray: PInt): DoubleArray;stdcall; external DLLDirectory;

错误的调用代码

procedure TForm7.btn1Click(Sender: TObject);
var
  AmplitudeData, FrequencyData : DoubleArray;
  arraylengths: array[0..1] of int32;
  I: Integer;
  TempSize : Int32;
begin
  TempSize := 50;
  AmplitudeData := AllocateDoubleArray(@Tempsize);
  FrequencyData := AllocateDoubleArray(@Tempsize);
  ReadTERFCorrectedData(fileloc, ArrayLengths[0], @AmplitudeData, @FrequencyData, 50);
  ShowMessage(arraylengths[1].tostring);
end;

修正方案及数据访问方法

1. 修正Delphi类型与函数声明

严格匹配DLL的调用约定与参数类型:

type
  Int32 = Integer; // 确保与C的int32_t类型一致
  DoubleArrayBase = packed record
    dimSizes: array[0..1] of Int32; // 存储数组的2维尺寸
    NumericControl: array[0..0] of Double; // 柔性数组,实际承载所有数据
  end;
  PDoubleArrayBase = ^DoubleArrayBase;
  DoubleArray = ^PDoubleArrayBase; // 对应C的DoubleArrayBase**类型
  PDoubleArray = ^DoubleArray;

  // 注意AllocateDoubleArray等函数为__cdecl调用约定
  function AllocateDoubleArray(dimSizeArr: PInt32): DoubleArray; cdecl; external 'YourDllName.dll';
  function ResizeDoubleArray(hdlPtr: PDoubleArray; dimSizeArr: PInt32): Integer; cdecl; external 'YourDllName.dll';
  function DeAllocateDoubleArray(hdlPtr: PDoubleArray): Integer; cdecl; external 'YourDllName.dll';

  // ReadTERFCorrectedData为__stdcall调用约定
  procedure ReadTERFCorrectedData(FilepathString: PAnsiChar;
                                  ArrayLengths: PInt32; // 传入2维数组指针
                                  AmplitudeData: PDoubleArray;
                                  FrequencyData: PDoubleArray;
                                  len: Int32); stdcall; external 'YourDllName.dll';

2. 正确调用DLL并访问数据

procedure TForm7.btn1Click(Sender: TObject);
var
  AmplitudeData, FrequencyData : DoubleArray;
  arrayLengths: array[0..1] of Int32;
  tempSize: array[0..1] of Int32; // 用2维数组匹配DLL的尺寸参数
  basePtr: PDoubleArrayBase;
  dataVal: Double;
  i: Integer;
begin
  // 初始化分配尺寸(按1维50元素预分配,DLL可能自动调整)
  tempSize[0] := 50;
  tempSize[1] := 1;

  // 分配数组资源
  AmplitudeData := AllocateDoubleArray(@tempSize);
  FrequencyData := AllocateDoubleArray(@tempSize);

  try
    // 调用读取函数,传入正确的参数指针
    ReadTERFCorrectedData(PAnsiChar(AnsiString(fileloc)), @arrayLengths, @AmplitudeData, @FrequencyData, 50);

    // 访问AmplitudeData中的数据
    if Assigned(AmplitudeData) then
    begin
      basePtr := AmplitudeData^; // 解第一层指针,得到DoubleArrayBase的指针
      if Assigned(basePtr) then
      begin
        // 输出数组尺寸信息
        ShowMessage(Format('数组维度:%d × %d', [basePtr.dimSizes[0], basePtr.dimSizes[1]]));

        // 遍历访问所有数据元素
        for i := 0 to basePtr.dimSizes[0] * basePtr.dimSizes[1] - 1 do
        begin
          // 通过指针偏移访问柔性数组中的元素
          dataVal := PDouble(@basePtr.NumericControl[i])^;
          // 处理数据,如输出或存储
          ShowMessage(Format('第%d个数据:%f', [i, dataVal]));
        end;
      end;
    end;
  finally
    // 释放数组资源,避免内存泄漏
    DeAllocateDoubleArray(@AmplitudeData);
    DeAllocateDoubleArray(@FrequencyData);
  end;
end;

关键注意点

  • 调用约定匹配:AllocateDoubleArray等函数为__cdecl,必须声明为cdecl;ReadTERFCorrectedData为__stdcall,声明为stdcall,否则会导致栈溢出或调用失败。
  • 参数类型修正:ArrayLengths是C的int32_t数组,需传入数组指针而非单个元素。
  • 嵌套指针解引用:DoubleArray是二级指针,需通过AmplitudeData^得到结构体指针后,才能访问成员。
  • 柔性数组访问:NumericControl是C的柔性数组,需通过指针偏移@basePtr.NumericControl[i]来访问第i个元素。

内容的提问来源于stack exchange,提问作者Shawn Vance

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:45:28