为什么SetString内在函数会导致PChar参数出现"不兼容类型"错误?

OnT*_*Fly 4 delphi delphi-xe2

请原谅这个愚蠢的问题,但我很困惑.考虑以下方法(抱歉嘈杂的评论,这是一个正在开发的真实代码):

function HLanguages.GetISO639LangName(Index: Integer): string;
const
  MaxIso639LangName = 9;  { see msdn.microsoft.com/en-us/library/windows/desktop/dd373848 }
var
  LCData: array[0..MaxIso639LangName-1] of Char;
  Length: Integer;
begin
  { TODO : GetLocaleStr sucks, write proper implementation }
  //Result := GetLocaleStr(LocaleID[Index], LOCALE_SISO639LANGNAME, '??');
  Length := GetLocaleInfo(LocaleID[Index], LOCALE_SISO639LANGNAME, @LCData, System.Length(LCData));
  Win32Check(Length <> 0);
  SetString(Result, @LCData, Length); // "E2008 Incompatible types" here, but why?
end;
Run Code Online (Sandbox Code Playgroud)

如果我删除了引用运算符,那么隐式转换$X+来自救援和方法编译.为什么编译器使用引用运算符拒绝此代码是我无法理解的.

这是Delphi XE2,这种行为可能是特定的.


如果我在HLanguages.GetISO639LangName这个错误的范围内添加一个具有等效原型的测试用例假人作为内在原型将神奇地消失:

procedure SetString(var s: string; buffer: PChar; len: Integer);
begin
  { test case dummy }
end;
Run Code Online (Sandbox Code Playgroud)

Arn*_*hez 5

你必须明确地将其转换为PChar:

SetString(result,PChar(@LCData),Length); 
Run Code Online (Sandbox Code Playgroud)

如你所述,SetString()对第二种参数类型要求很高.它必须是PChara PWideChar或者a PAnsiChar,取决于字符串类型本身.

我怀疑这是因为SetString()定义为a string,a WideStringAnsiStringas作为第一个参数的重载.因此,为了验证正确的签名,它需要与所有参数类型完全匹配:

SetString(var s: string; buf: PChar; len: integer); overload;
SetString(var s: AnsiString; buf: PAnsiChar; len: integer); overload;
SetString(var s: WideString; buf: PWideChar; len: integer); overload;
Run Code Online (Sandbox Code Playgroud)

当然,所有这些都是"内在函数",所以你不会在system.pas中找到这样的定义,而是直接在某些程序中找到这样的定义_LStrFromPCharLen() _UStrFromPCharLen() _WStrFromPWCharLen().

这种行为与Delphi的早期版本相同,并不是XE2中的回归.