Reputation:
I have a C based DLL that exports a function that has char*** as an argument, this is a pointer to a pointer to a pointer of char (Non-unicode) My question is, after much frustration, what is the equivalent declaration at the Delphi end?
I've tried for example:
// C Method declaration
void method (char*** arg)
TArrayOfPAnsiChar = array of PAnsiChar;
PArrayOfPAnsiChar = ^TArrayOfPAnsiChar;
PPArrayOfPAnsiChar = ^PArrayOfPAnsiChar;
// Delphi declaration
procedure method (var p : PPArrayOfPAnsiChar); cdecl;
p : PPArrayOfAnsiChar;
method (p)
But I'm not getting anything sensible back. Any suggestions? The var in the declaration is of course already a pointer so perhaps that's where I am going wrong. I've tried many variants, written down on paper what the structure is and reverse engineered a Delphi declration but to no avail. This DLL is used in other C based applications so I assume its functioning correctly.
Using XE6
Upvotes: 1
Views: 807
Reputation: 613511
In this case char*** is a pointer to a pointer that points to an array where each element points to a string.
This implies that the callee is returning data to the caller. So you want to use:
procedure method(out Arg: PPAnsiChar); cdecl; external dllname;
where PPAnsiChar
is ^PAnsiChar
. Note that PPAnsiChar
is defined in the System
unit.
The C code has three levels of indirection. The outermost is how function passses data from callee to caller. That's represented as a Delphi out
parameter. The remaining two levels of indirection are captured in PPAnsiChar
. Finally C's char
is an 8 bit type on Windows and so maps to AnsiChar
.
You will also need to iterate over the array when the function returns. Like this:
var
StrArr: PPAnsiChar;
Str: string;
....
method(StrArr);
while StrArr^ <> nil do
begin
Str := StrArr^;
Inc(StrArr);
end;
I'm assuming that the length of the array is indicated by a terminating null pointer. If instead you are told the length, you use a for loop as should be obvious.
Upvotes: 1
Reputation: 13332
Don't use array of
, because that declares a dynamic array, and use AnsiChar
rather than Char
, since the latter is two bytes in Delphi.
PPAnsiChar = ^PAnsiChar;
PPPAnsiChar = ^PPAnsiChar;
procedure Method(Arg: PPPAnsiChar); cdecl;
or
procedure Method(var Arg: PPAnsiChar); cdecl;
If you want to index into the variable like an array, add {$POINTERMATH ON}
before declaring the types
Upvotes: 10