我正在尝试使用本地程序中的C++动态链接库。我遵循的是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');控制进入动态链接库,但是szIp和szPort形参只接收我从delphi程序传递的ip和端口的第一个字符。
我知道这与在delphi中正确地使用null来终止字符串有关。所以我也尝试了下面的方法。
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 pzIp和pzPort时,我得到了奇怪的结果。
忘了说了,C++ dll中的所有成员函数都是用__stdcall编译的,并正确导出
发布于 2009-09-09 11:36:46
在Delphi2010(和Delphi2009)中,"char“类型实际上是一个WIDEChar -即16位宽。因此,当你调用你的C++函数时,如果它期望字符是8位宽(所谓的"ANSI",而不是UNICODE),那么它就会错误地解释输入参数。
例如,如果你传递字符串'ABC'#0 (我显式地显示了空终止符,但这只是Delphi语言中字符串的隐式部分,不需要特别添加),这将传递一个指向8字节序列的指针,而不是4字节!
但是,因为字符串中的3个字符只有8位代码点值(在Unicode术语中,这意味着C++代码“看到”的是如下所示的字符串:
'A'#0'B'#0'C'#0#0#0这就解释了为什么您的C++代码似乎只获取字符串的第一个字符-它在第一个字符的第二个字节中看到#0,并假设它是整个字符串的空终止符。
您需要修改C++代码以正确接收指向WideChar字符串的指针,或者修改Delphi中的函数签名,并在将字符串传递给C++函数之前在Delphi代码中将字符串转换为ANSIString:
修改后的函数签名:
function Setup(ip, port: PANSIChar):Integer: virtual; stdcall; abstract;以及相应的“长手”,在调用函数之前显示字符串到ANSIString的转换-编译器可能会为您处理这一点,但您可能会发现在代码中清楚地说明这一点而不是依赖于“编译器魔术”是有帮助的:
var
sIPAddress: ANSIString;
sPort: ANSIString;
begin
sIPAddress := '192.168.1.100';
sPort := '97777';
pObj.Setup(sIPAddress, sPort);
// etc... 发布于 2009-09-09 11:03:53
两个编译器中的char大小是否相同?如果您使用的是D2009/D2010,则char现在是16位。
发布于 2009-09-09 10:21:58
如果我理解正确的话,你的函数原型也应该是stdcall。
function Setup(ip, port: PChar):Integer: virtual; stdcall; abstract;ps。Delphi字符串已经以null结尾。
https://stackoverflow.com/questions/1398763
复制相似问题