如何在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
相关产品推荐
相关产品推荐

