I have a DLL with the following header definitions:
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);
My question is, how do I go about setting up a Delphi call to this function?
My Delphi definition of the call is as follows:
type
PTheStruct = ^TheStruct;
TheStruct= record
dimSizes: array of integer;
NumericControl: array of Double;
end;
procedure ReadTERFCorrectedData(asFilePathString: AnsiString; ArrayLength: pint; arAmplitude, arFrequency: PThestruct; TheLength : Integer );stdcall; external DLLDirectory;
But I don't even know if I'm on the right track.
CodePudding user response:
The DLL is using fixed-length arrays, but your Delphi code is using dynamic arrays instead. They are not the same thing.
Also, the DLL is expecting a pointer-to-pointer-to-struct, but you are using a pointer-to-record instead. You are missing a level of indirection.
Also, the DLL expects a pointer to a null-terminated AnsiChar
C string, not an AnsiString
.
Try this instead:
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;
ArrayLengths: PInt32; AmplitudeData, FrequencyData: PDoubleArray;
len: Int32); stdcall; external '...';
// Alternatively:
//
// procedure ReadTERFCorrectedData(FilepathString: PAnsiChar;
// var ArrayLengths: Int32; var AmplitudeData, FrequencyData: DoubleArray;
// len: Int32); stdcall; external '...';
UPDATE: the function takes DoubleArray*
parameters, ie a pointer to a DoubleArray
. So you likely need to call it something like this:
procedure TForm7.btn1Click(Sender: TObject);
var
AmplitudeData, FrequencyData : DoubleArray;
ArrayLengths: array[0..1] of Int32;
I: Integer;
begin
ReadTERFCorrectedData(fileloc, @ArrayLengths[0], @AmplitudeData, @FrequencyData, 500);
...
end;
But, there is simply not enough information presented to know whether you need to pre-allocate the arrays before calling the function, or if the function will allocate the arrays for you. The use of pointer-to-pointer indirections strongly implies that the DLL will perform the allocations for you. But what the DoubleArray
contents will look like upon exit is anyone's guess without seeing documentation or example C code.
CodePudding user response:
Using Remy's answer, how whould one go about calling the DLL? This seems to work, but i am only getting 0's in my array's, Which i am certain is not correct.
type
PDoubleArray = ^DoubleArray;
DoubleArray = ^PDoubleArrayBase;
PDoubleArrayBase = ^DoubleArrayBase;
DoubleArrayBase = record
dimSizes: array[0..1] of Int32;
NumericControl: array[0..0] of Double;
end;
procedure ReadTERFCorrectedData(FilepathString: PAnsiChar;
ArrayLengths: PInt32; AmplitudeData, FrequencyData: PDoubleArray;
len: Int32); stdcall; external '...';
implementation
{$R *.dfm}
procedure TForm7.btn1Click(Sender: TObject);
var
AmplitudeData, FrequencyData : array of DoubleArrayBase;
arraylengths: array of Integer;
I: Integer;
begin
SetLength(AmplitudeData,500);
SetLength(FrequencyData,500);
SetLength(arraylengths,2);
ReadTERFCorrectedData(fileloc,@arraylengths[0], @AmplitudeData[0], @FrequencyData[0],500);
for I := 0 to 499 do
begin
mmo1.Lines.Add(FrequencyData[i].NumericControl[0].ToString);
mmo1.Lines.Add(frequencydata[i].dimsizes[0].tostring);
mmo1.Lines.Add(frequencydata[i].dimsizes[1].tostring);
end;
end;