Delphi PChar到C ++ const char *

时间:2009-09-09 10:16:08

标签: c++ delphi dll

我正在尝试使用本机程序中的C ++ DLL。我正在按照here

所述的虚拟方法场景进行操作

让我说我的C ++函数签名的形式是

int Setup(const char* szIp, const char* szPort);

相应的delphi签名是

function Setup(ip, port: PChar):Integer: virtual; cdecl; abstract;

从delphi程序的某个地方我可以调用

pObj.Setup('192.168.1.100', '97777');

控件进入dll,但是szIp和szPort形式参数只接收我从delphi程序传递的ip和port的第一个字符。

我知道它与null在delphi中正确终止字符串有关。所以我也试过了以下内容。

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.

这也是一种工作方式。当我Writeln pzIppzPort时,我得到了奇怪的结果。

忘了说,来自C ++ dll的所有成员函数都使用__stdcall进行编译并正确导出

3 个答案:

答案 0 :(得分:17)

在Delphi 2010(和Delphi 2009)中,“char”类型实际上是WIDEChar - 即16位宽。因此,当您调用C ++函数时,如果期望CHAR为8位宽(所谓的“ANSI”,而不是UNICODE),那么它将错误解释输入参数。

e.g。如果你传递字符串'ABC'#0 (我显式地显示空终止符,但这只是Delphi中字符串的隐式部分,不需要特别添加)指向 8字节序列的指针, NOT 4字节!

但是因为字符串中的3个字符只有8位代码点值(在Unicode术语中,这意味着C ++代码“看到”的字符串看起来像:

  'A'#0'B'#0'C'#0#0#0

这可以解释为什么你的C ++代码似乎只是获得字符串的第一个字符 - 它在第一个字符的第二个字节中看到#0 并假设它是整个字符串的空终止符。

您需要修改C ++代码以正确接收指向 WideChar 字符串的指针,或修改Delphi中的函数签名并将字符串转换为Delphi代码中的 ANSIString 之前将它们传递给C ++函数:

修改功能签名:

  function Setup(ip, port: PANSIChar):Integer: virtual; stdcall; abstract;

和相应的“Long hand”显示在调用函数之前将字符串转换为 ANSIString - 编译器可能会为您解决此问题,但您可能会发现在代码中明确这一点很有帮助而不是依赖“编译魔术”:

  var
    sIPAddress: ANSIString;
    sPort: ANSIString;
  begin   
    sIPAddress := '192.168.1.100';
    sPort      := '97777';

    pObj.Setup(sIPAddress, sPort);

    // etc... 

答案 1 :(得分:4)

两个编译器中的char大小相同吗?如果您使用的是D2009 / D2010,则char现在为16位。

答案 2 :(得分:3)

如果我理解正确,你的函数原型也应该是stdcall。

function Setup(ip, port: PChar):Integer: virtual; stdcall; abstract;

PS。 Delphi字符串已经以空值终止。