0

ANSI テキスト (PAnsiChar) へのポインターを返す DLL 関数があります。これを(unicode-)文字列に割り当てたい(これはDelphi XE2です)。以下はコンパイルされますが、「W1057 Implicit String cast from 'AnsiChar' to '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 以降のバージョンでもコンパイルおよび動作するはずです。

4

2 に答える 2

5

テキストがユーザーの現在のロケールでエンコードされている場合、次のように書くのが最も簡単だと思います。

var
  p: PAnsiChar;
  str: string;
....
str := string(p);

それ以外の場合は、特定のコード ページから Unicode 文字列に変換する場合は、UnicodeFromLocaleChars.

于 2015-01-09T09:39:05.993 に答える
3

一般的な解決策は、c char ポインターを RawByteString に割り当て、そのコードページを c ヌル終了文字列エンコーディングに対応するように設定することだと思います。

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;

もう 1 つのクロスプラットフォーム ソリューションは (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;
于 2015-01-10T07:31:42.927 に答える