所以问题是Delphi 2009/2010中的字符串文字(或const字符串)是否可以直接转换为PAnsiChar,还是首先需要对AnsiString进行额外的转换才能使其工作?
背景是我在具有C接口的旧DLL中调用函数,该接口具有一些需要C样式的char指针的函数.在过去(在Delphi 2009之前),像下面这样的代码就像一个魅力(其中C DLL函数的参数是LPCSTR):
之一:
LegacyFunction(PChar('Fred'));
Run Code Online (Sandbox Code Playgroud)
要么
const
FRED = 'Fred';
...
LegacyFunction(PChar(FRED));
Run Code Online (Sandbox Code Playgroud)
因此,在更改为Delphi 2009(现在是2010年)时,我将调用更改为:
LegacyFunction(PAnsiChar('Fred'));
Run Code Online (Sandbox Code Playgroud)
要么
const
FRED = 'Fred';
...
LegacyFunction(PAnsiChar(FRED));
Run Code Online (Sandbox Code Playgroud)
这似乎工作,我从函数调用得到正确的结果.然而,应用程序中存在一些明确的不稳定性,这些不稳定似乎主要发生在调用遗留函数的代码中的第二次或第三次(在转移到2009版本的IDE之前不存在).在研究这个时,我意识到Delphi 2009/2010中的本地字符串文字(和const字符串)是一个Unicode字符串,所以我的演员可能是错误的.这里和其他地方的示例似乎表明此调用看起来应该更像这样:
LegacyFunction(PAnsiChar(AnsiString('Fred')))
Run Code Online (Sandbox Code Playgroud)
令我困惑的是,使用上面第二个示例中的代码,将字符串文字直接转换为PAnsiChar不会生成任何编译器警告.如果不是字符串文字,我正在构建一个字符串var,我会得到一个可疑的强制警告(并且该字符串会被修复).这(以及字符串在DLL中可用的事实)使我相信编译器正在做一些魔术来正确地将字符串文字解释为预期的字符串类型.这是发生了什么,或者是双重演员(首先是AnsiString,然后是PAnsiChar)真的有必要,而且在我的代码中缺少它是难以追踪不稳定的原因吗?对于const字符串,同样的答案是否也适用?
对于类型推断的常量(只能从文字中初始化),编译器会在编译时更改实际文本,而不是在运行时更改.这意味着它知道转换是否会丢失数据,因此如果没有,则不需要发出警告.
"想象"Barry Kelly和Mason Wheeler的话:
const
FRED = 'Fred';
var
p: PAnsiChar;
w: PWideChar;
begin
w := PWideChar(Fred);
p := PAnsiChar(Fred);
In ASM:
Unit7.pas.32: w := PWideChar(Fred);
00462146 BFA4214600 mov edi,$004621a4
// no conversion, just a pointer to constant/"-1 RefCounted" UnicodeString
Unit7.pas.33: p := PAnsiChar(Fred);
0046214B BEB0214600 mov esi,$004621b0
// no conversion, just a pointer to constant/"-1 RefCounted" AnsiString
Run Code Online (Sandbox Code Playgroud)
正如您在PWideChar/PChar(FRED)和PAnsiChar(FRED)两种情况下所看到的,没有转换,Delphi编译器会生成2个常量字符串,一个AnsiString和一个UnicodeString.
| 归档时间: |
|
| 查看次数: |
4982 次 |
| 最近记录: |