我有一个DLL函数,它返回一个指向ANSI文本(PAnsiChar)的指针。我想将它分配给(unicode-)字符串(这是Delphi XE2。)。以下编译,但我收到警告 “W1057隐式字符串从'AnsiChar'转换为'string'”:
function TProj4.pj_strerrno(_ErrorCode: Integer): string;
var
Err: PAnsiChar;
begin
Err := Fpj_strerrno(_ErrorCode);
Result := Err;
end;
编辑:有问题的文字是英文错误信息,所以这里不太可能有任何转换问题。
我现在很想明确地将Err强制转换成这样的字符串......
Result := String(Err);
..摆脱警告。这可能会出错吗?我宁愿使用临时的AnsiString变量吗?
var
s: AnsiString;
[...]
s := Err;
Result := String(s);
如果是,为什么?
或者我应该明确说明,代码首先将PAnsiChar转换为AnsiString,然后将AnsiString转换为String?
Result := String(AnsiString(Err));
当然,我可以把它变成一个功能:
function PAnsicharToString(_a: PAnsiChar): string;
begin
// one of the above conversion codes goes here
end;
所有这些选项都会编译,但是它们会起作用吗?这里最好的做法是什么?
奖励要点:理想情况下,代码应该与Delphi 2007及更新版本一起编译和使用。
答案 0 :(得分:5)
如果文本是在用户当前的语言环境中编码的,那么我会说它写起来最简单:
var
p: PAnsiChar;
str: string;
....
str := string(p);
否则,如果您希望从特定代码页转换为Unicode字符串,则可以使用UnicodeFromLocaleChars
。
答案 1 :(得分:3)
我认为通用解决方案是将c char指针分配给RawByteString,然后将其代码页设置为对应于以null结尾的字符串编码。
var
bys :TBytes;
rbstr :RawByteString;
ustr :string;
pastr :PAnsiChar;
begin
SetLength(bys,5);
bys[0] := $ca;
bys[1] := $e9;
bys[2] := $d2;
bys[3] := $b5;
bys[4] := 0;
pastr := @bys[0]; // just simulate char* returned by c api
rbstr := pastr; // assign PAnsiChar to RawByteString
// assume text encoded as codepage 936
// Note here: set 3rd param to false!
SetCodePage(rbstr,936,false);
ustr := string(rbstr);
ShowMessage(ustr);
end;
另一个跨平台解决方案是(vcl,fmx,fmx with mobile platform)
function CString2TBytes(ptr :{$IFDEF NEXTGEN} MarshaledAString {$ELSE} PAnsiChar {$ENDIF}) :TBytes;
var
pby :PByte;
len :Integer;
begin
pby := PByte(ptr);
while pby^<>0 do Inc(pby);
len := pby - ptr;
SetLength(Result,len);
if len>0 then Move(ptr^,Result[0],len);
end;
procedure TForm5.Button1Click(Sender: TObject);
var
bys, cbys: TBytes;
ustr: string;
// PAnsiChar is undefined in mobile platform
// remap param foo(outSting:PAnsiString) => foo(outString:MarshaledAString)
ptr: {$IFDEF NEXTGEN} MarshaledAString {$ELSE} PAnsiChar {$ENDIF}; //
encoding : TEncoding;
begin
SetLength(bys, 5);
bys[0] := $CA;
bys[1] := $E9;
bys[2] := $D2;
bys[3] := $B5;
bys[4] := 0;
ptr := @bys[0]; // just simulate char* returned by c api
cbys := CString2TBytes(ptr);
// assume text encoded as codepage 936
encoding := TEncoding.GetEncoding(936);
try
ustr := encoding.GetString(cbys);
ShowMessage(ustr);
finally
encoding.Free;
end;
end;
答案 2 :(得分:-1)
回到前Unicode时代,它是MultiByteToWideChar / WideCharToMultiByte,它是代码页和字符集转换的首选工具。 http://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx 两者都要求您知道源/目标的CP。 更多信息:http://msdn.microsoft.com/en-us/library/windows/desktop/dd317752(v=vs.85).aspx