Reputation: 895
I have a DLL, written in XE2 that takes a PChar as a parameter (therefore being a unicode string). I was hoping to write an application in Delphi 2006 that calls this DLL. Is this possible, how do I pass in the PChar parameter? If I was doing it in Delphi XE2 I would simply do:
tmpString := 'hello';
DLL_Call(PChar(tmpString));
I have tried defining my tmpString as a WideString in Delphi 2006, but I believe a WideString and an XE2 Unicode string differ considerably?
Is there a way I can pass the string correctly to the DLL? I am in control of the DLL source code so I could obviously change the function definition to PAnsiChar but I'd prefer not to do this, I was hoping for a solution from the Delphi 2006 side if possible.
Upvotes: 0
Views: 2604
Reputation: 596397
It really depends on how the DLL uses the PWideChar
that is passed to it. As long as the DLL does not make any assumptions about how the memory is allocated, it only reads from the memory or writes into the memory, then a WideString
will work just fine. Widestring
and UnicodeString
are managed differently by the RTL, but they both contain UTF-16 encoded payloads, so they are content-compatible with each other. Both also contain a #0
character at the end of their payloads, which is important since the DLL only accepts a PChar
pointer, so both string types are treated as null-terminated by the DLL when casted to PChar
. To avoid that dependancy, you should update the DLL to accept the string length as a parameter as well, eg:
D2006:
function DLL_Call(S: PWideChar; L: Integer); stdcall; external 'mylib.dll';
var
tmpString: WideString;
tmpString := 'hello';
DLL_Call(PWideChar(tmpString), Length(tmpString));
XE2:
function DLL_Call(S: PChar; L: Integer); stdcall; external 'mylib.dll';
var
tmpString: String;
tmpString := 'hello';
DLL_Call(PChar(tmpString), Length(tmpString));
Upvotes: 0
Reputation:
I have tried defining my tmpString as a WideString in Delphi 2006, but I believe a WideString and an XE2 Unicode string differ considerably?
They do. However, they can both be converted from/to a C-style #0-terminated array of WideChar, in other words PWideChar. The only potential problem is that you cannot pass in strings that contain #0 other than as a terminator.
Your objection would be valid if you attempted to call a function accepting a UnicodeString
with a WideString
argument, but that's not what you're doing. So the solution you already found is the right one.
Upvotes: 2
Reputation: 612993
You need to declare the function as receiving a PWideChar
. And then use WideString
to hold the payload.
function DLL_Call(S: PWideChar); stdcall; external 'mylib.dll';
......
var
tmpString: WideString;
......
tmpString := 'hello';
DLL_Call(PWideChar(tmpString));
Remember that PChar
is an alias. In pre-Unicode Delphi it is an alias to PAnsiChar
. In Unicode Delphi it is an alias to PWideChar
. Pre-Unicode Delphi is perfectly capable of calling any Unicode APIs, but must use PWideChar
explicitly.
Upvotes: 3