Steve Magness
Steve Magness

Reputation: 895

Unicode PChar from Delphi 2006

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

Answers (3)

Remy Lebeau
Remy Lebeau

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

user743382
user743382

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

David Heffernan
David Heffernan

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

Related Questions