类型不兼容:'PAnsiChar' 和 'PWideChar'

8

我在Delphi XE8方面很新。我有以下代码来自我的Delphi 6版本,我想在Delphi XE8中运行它。

1. function UTF8ToStringLen(const src: PChar; const Len: Cardinal): widestring;
2. var
3.   l: Integer;
4. begin
5.   SetLength(Result, Len);
6.   if Len > 0 then
7.   begin                                             
8.     l := MultiByteToWideChar( CP_UTF8, 0, src, Len, PWChar(Result), Len*SizeOf(WideChar));  <--error
9.     SetLength(Result, l);
10.   end;
11. end;
12. 
13. 
14. function StringToUTF8Len(const src: PChar; const Len: Cardinal): string;
15. var
16.   bsiz: Integer;
17.   Temp: string;
18. begin
19.   bsiz := Len * 3;
20.   SetLength(Temp, bsiz);
21.   if bsiz > 0 then
22.   begin
23.     StringToWideChar(src, PWideChar(Temp), bsiz);
24.     SetLength(Result, bsiz);                
25.     bsiz := WideCharToMultiByte(CP_UTF8, 0, PWideChar(Temp), -1, PChar(Result), bsiz, nil, nil);  <--error
26.     if bsiz > 0 then dec(bsiz);
27.     SetLength(Result, bsiz);
28.   end;
29. end;

当我试图运行代码时,出错信息指向代码的第8行和第25行,并显示一个错误消息。
ERROR MESSAGE: Incompatible types: 'PAnsiChar' and 'PWideChar'

我已经到处寻找解决方案,但是我无法解决这个问题。请帮忙...谢谢。


1
由于XE8启用了Unicode,因此PChar类似于PWideChar。为解决您的问题,请声明src:PAnsiChar。但您可能还需要做更多的工作。我建议阅读Marco Cantú关于Unicode的白皮书:http://edn.embarcadero.com/article/38980。 - Uwe Raabe
2个回答

14
在Delphi 2007及之前的版本中,PCharPAnsiChar的别名。在Delphi 2009及之后的版本中,PCharPWideChar的别名。因此,更改编译器会改变代码的含义。
您可以将PChar替换为PAnsiChar来解决这个问题,代码将恢复其原始含义。
在现代Unicode Delphi中,使用string(别名为UnicodeString)而不是COM WideString更加自然。您还可以使用许多库函数来执行UTF-8转换。
您肯定会遇到其他问题。我建议您阅读Marco Cantù有关Delphi中Unicode的白皮书以进一步处理。

1
又是一次似曾相识的经历。 - Rudy Velthuis

3

来自MSDN:

  • MultiByteToWideChar function

    int MultiByteToWideChar(
     _In_      UINT   CodePage,
     _In_      DWORD  dwFlags,
     _In_      LPCSTR lpMultiByteStr,
     _In_      int    cbMultiByte,
     _Out_opt_ LPWSTR lpWideCharStr,
     _In_      int    cchWideChar
    );
    
  • WideCharToMultiByte function

    int WideCharToMultiByte(
     _In_      UINT    CodePage,
     _In_      DWORD   dwFlags,
     _In_      LPCWSTR lpWideCharStr,
     _In_      int     cchWideChar,
     _Out_opt_ LPSTR   lpMultiByteStr,
     _In_      int     cbMultiByte,
     _In_opt_  LPCSTR  lpDefaultChar,
     _Out_opt_ LPBOOL  lpUsedDefaultChar
    );
    
  • From Windows Data Types:

    LPCSTR
    A pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.
    This type is declared in WinNT.h as follows:
    typedef __nullterminated CONST CHAR *LPCSTR;

    LPSTR
    A pointer to a null-terminated string of 8-bit Windows (ANSI) characters.
    This type is declared in WinNT.h as follows:
    typedef CHAR *LPSTR;

您的代码问题在于每个函数的参数lpMultiByteStr都是一个PAnsiChar,而您正在将PChar作为参数传递。
Delphi 6 中, PChar PAnsiChar 的别名,而在 Delphi XE8 中则表示 PWideChar

  • 您可以通过在第8行声明函数(并相应地调用它)来解决此问题:
    function UTF8ToStringLen(const src: PAnsiChar; const Len: Cardinal): WideString;

  • 为了解决第25行的问题,请更改函数声明如下:
    function StringToUTF8Len(const src: PAnsiChar; const Len: Cardinal): string;
    以及"臭名昭著"的语句:
    bsiz := WideCharToMultiByte(CP_UTF8, 0, PWideChar(Temp), -1, PAnsiChar(Result), bsiz, nil, nil);

每种情况都适用David Heffernan's solution


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接