来自Delphi 2006的Unicode PChar

时间:2012-06-29 09:15:50

标签: delphi dll unicode

我有一个用XE2编写的DLL,它以PChar作为参数(因此是一个unicode字符串)。我希望在Delphi 2006中编写一个调用此DLL的应用程序。这是可能的,我如何传递PChar参数?如果我在Delphi XE2中这样做,我只会这样做:

tmpString := 'hello';
DLL_Call(PChar(tmpString));

我在Delphi 2006中尝试将我的tmpString定义为WideString,但我相信WideString和XE2 Unicode字符串差异很大?

有没有办法可以将字符串正确传递给DLL?我控制DLL源代码,所以我显然可以将函数定义更改为PAnsiChar,但我不想这样做,我希望尽可能从Delphi 2006方面获得解决方案。

3 个答案:

答案 0 :(得分:3)

您需要将该函数声明为接收PWideChar。然后使用WideString来保存有效负载。

function DLL_Call(S: PWideChar); stdcall; external 'mylib.dll';

......
var
  tmpString: WideString;
......
tmpString := 'hello';
DLL_Call(PWideChar(tmpString));

请记住,PChar是别名。在Unicode前Delphi中,它是PAnsiChar的别名。在Unicode Delphi中,它是PWideChar的别名。 Pre-Unicode Delphi完全能够调用任何Unicode API,但必须明确使用PWideChar

答案 1 :(得分:2)

  

我在Delphi 2006中尝试将我的tmpString定义为WideString,但我相信WideString和XE2 Unicode字符串差异很大?

他们这样做。但是,它们都可以从/转换为C风格的#0端接的WideChar数组,换句话说就是PWideChar。唯一可能的问题是你不能传入包含#0的字符串而不是作为终结符。

如果您尝试调用接受带有UnicodeString参数的WideString的函数,您的异议将是有效的,但这不是您正在做的事情。所以你已经找到的解决方案是正确的。

答案 2 :(得分:0)

这实际上取决于DLL如何使用传递给它的PWideChar。只要DLL没有对内存的分配方式做出任何假设,它只会从内存中读取或写入内存,那么WideString就可以了。 RTL对WidestringUnicodeString进行了不同的管理,但它们都包含UTF-16编码的有效负载,因此它们彼此内容兼容。两者在其有效负载的末尾都包含#0字符,这很重要,因为DLL只接受PChar指针,因此当转换为{时,两个字符串类型都被DLL视为由null终止{1}}。为了避免这种依赖性,您应该更新DLL以接受字符串长度作为参数,例如:

D2006:

PChar

XE2:

function DLL_Call(S: PWideChar; L: Integer); stdcall; external 'mylib.dll'; 

var 
  tmpString: WideString; 

tmpString := 'hello'; 
DLL_Call(PWideChar(tmpString), Length(tmpString));