【问题标题】:Suspicious typecast of RawByteString to PWideCharRawByteString 到 PWideChar 的可疑类型转换
【发布时间】:2019-09-11 15:55:12
【问题描述】:

我使用 libxml2 (http://www.xmlsoft.org/) 在我的 Delphi 代码中读取/写入 xml 文件。 libxml2 对所有字符串使用 UTF-8 编码。

例如函数xmlsavefile在libxml2中定义为

int xmlSaveFile (const char * filename, xmlDocPtr cur)

在 libxml2 Delphi 绑定中这个函数被翻译成

const LIBXML2_SO = 'libxml2-2.dll';
function xmlSaveFile(const FileName: PChar; cur: xmlDocPtr) : Longint; cdecl; external LIBXML2_SO;

这个函数可以作为

var FileName : string;
xmlSaveFile(PChar(Utf8Encode(FileName)), doc);

这似乎没有任何问题,并且已经用包括中文在内的各种语言进行了测试。但是,我收到编译器警告

RawByteString 到 PWideChar 的可疑类型转换

由于一切正常,我倾向于忽略此警告。尽管如此,

  • 我可以去掉这个警告吗?
  • 我必须预料到任何问题吗?

【问题讨论】:

    标签: delphi utf-8 libxml2 delphi-xe5


    【解决方案1】:

    错误在导入函数的声明中:

    function xmlSaveFile(const FileName: PChar; cur: xmlDocPtr) : Longint; cdecl; 
      external LIBXML2_SO;
    

    此函数接受 8 位 UTF8 编码的文件名。这可以从将文件名参数声明为const char * 的C 代码中看出。

    将代码改为:

    function xmlSaveFile(const FileName: PAnsiChar; cur: xmlDocPtr) : Longint; cdecl; 
      external LIBXML2_SO;
    

    然后通过:

    PAnsiChar(Utf8Encode(FileName))
    

    【讨论】:

    • 值得注意的是,Utf8Encode 返回定义为RawByteString = type AnsiString($ffff);RawByteString 类型,即:与代码页无关的AnsiString。该警告是由单字节字符串类型隐式转换为多字节PChar 类型引起的。
    • 请注意,UTF8Encode() 自 D2009 以来已被弃用,您可以简单地将类型转换为 UTF8StringPAnsiChar(UTF8String(FileName))
    【解决方案2】:

    您使用的 Delphi 绑定已经过时,可能是在 Delphi 2009 之前编写的,当时 (P)Char 仍然是 (P)AnsiChar 的别名。从 Delphi 2009 开始,(P)Char 现在是 (P)WideChar 的别名。所以编译器警告是正确的 - 你确实是在将 UTF8Encode() 返回的 RawByteString 类型转换为 PWideChar 而不是 PAnsiChar

    您需要更新绑定(或获取更新版本,或找到已进行更新的不同绑定)以在libxml2 使用char* 字符串的任何地方显式使用PAnsiChar,例如:

    function xmlSaveFile(const FileName: PAnsiChar; cur: xmlDocPtr) : Longint; cdecl; external LIBXML2_SO;
    

    然后更新您的代码以匹配:

    var FileName : string;
    xmlSaveFile(PAnsiChar(UTF8Encode(FileName)), doc);
    
    var FileName : string;
    xmlSaveFile(PAnsiChar(UTF8String(FileName)), doc);
    
    var FileName : UTF8String;
    xmlSaveFile(PAnsiChar(FileName), doc);
    

    【讨论】:

    • 我能找到的 libxml2 的 Delphi 绑定的最新版本大约有 10 年的历史了,所以开发似乎暂停了。
    • libxml2.pas 定义类型 xmlCharPtr = PAnsiChar;但这只是偶尔使用,并非无处不在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-04
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多