I am trying to use a C++ dll from a native program. I am following the virtual method scenario as explained here
Lets say my C++ function signature is of the form
int Setup(const char* szIp, const char* szPort);
And the corresponding delphi signature is
function Setup(ip, port: PChar):Integer: virtual; cdecl; abstract;
And somewhere from the delphi program i can call
pObj.Setup('192.168.1.100', '97777');
The control comes into the dll, but szIp and szPort formal parameters only receives the first character of the ip and port that I had passed from the delphi program.
I understand that it has to do with null terminating the string properly in delphi. So i had tried the following too.
var
pzIp, pzPort: PChar;
szIp, szPort: string;
begin
szIp := '192.168.1.2';
szPort := '9777';
//initilize memory for pchar vars
GetMem(pzIp, Length(szIp)+1);
GetMem(pzPort, Length(szPort)+1);
//null terminate the strings
pzIp[Length(szIp)+1] := #0;
pzPort[Length(szPort)+1] := #0;
//copy strings to pchar
StrPCopy(pzIp, szIp);
StrPCopy(pzPort, szPort);
end.
This a'int working either. When i Writeln
pzIp
and pzPort
I get strange results.
Forgot to tell, all member functions from the C++ dll are compiled with __stdcall
and exported properly
In Delphi 2010 (and Delphi 2009) the "char" type is actually a WIDEChar - that is, 16 bits wide. So when you call your C++ function, if that is expecting CHAR to be 8 bits wide (so called "ANSI", rather than UNICODE), then it is going to misinterpret the input parameter.
e.g. if you pass the string 'ABC'#0 (I'm showing the null terminator explicitly but this is just an implicit part of a string in Delphi and does not need to be added specifically) this passes a pointer to an 8 byte sequence, NOT 4 bytes!
But because the 3 characters in your string have only 8-bit code-point values (in Unicode terms, this means that what the C++ code "sees" is a string that looks like:
'A'#0'B'#0'C'#0#0#0
Which would explain why your C++ code seems only to be getting the first character of the string - it is seeing the #0 in the 2nd byte of that first character and assuming that it is the null terminator for the entire string.
You either need to modify your C++ code to correctly receive pointers to WideChar strings, OR modify the function signature in Delphi and convert your strings to ANSIString in the Delphi code before passing those to the C++ function:
Revised function signature:
function Setup(ip, port: PANSIChar):Integer: virtual; stdcall; abstract;
and the corresponding "Long hand" showing conversion of strings to ANSIString before calling the function - the compiler may take care of this for you but you might find it helpful to make it clear in your code rather than relying on "compiler magic":
var
sIPAddress: ANSIString;
sPort: ANSIString;
begin
sIPAddress := '192.168.1.100';
sPort := '97777';
pObj.Setup(sIPAddress, sPort);
// etc...
Is char the same size in both compilers? If you are using D2009/D2010, char is now 16-bits.
If I understand correctly your function prototype should be stdcall as well.
function Setup(ip, port: PChar):Integer: virtual; stdcall; abstract;
ps. Delphi strings are already null-terminated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With