3

次のコード スニペットを検討してください(Delphi XE2 の場合)。

function PrepData(StrVal: string; Base64Val: AnsiString): OleVariant;
begin
  Result := VarArrayCreate([0, 1], varVariant);
  Result[0] := StrVal;
  Result[1] := Base64Val;
end;

Base64ValBase64 としてエンコードされたバイナリ値です (したがって、nullバイトはありません)。( OleVariant) Resultは自動的にマーシャリングされ、クライアント アプリと DataSnap サーバーの間で送信されます。

Wireshark でトラフィックをキャプチャすると、 と の両方が Unicode 文字列として転送されていることがわかりStrValますBase64Val。できれば、 の Unicode 変換を避けたいと思いBase64Valます。私はすべてのタイプを見てきましたが、文字の配列を転送できるVariantもの以外は見当たりません。varString

バイトのバリアント配列を作成する方法を示すこの質問を見つけました。を使用する代わりに、この手法を使用できると考えていAnsiStringます。Unicode 文字列に変換せずに非 Unicode 文字データの配列を Variant に割り当てる別の方法はありますか?

4

2 に答える 2

4

Delphi の実装では、カスタム バリアント型コードを使用して、バリアントに AnsiString と UnicodeString を格納することがサポートされています。これらのコードは、varString および varUString です。

ただし、相互運用では通常、標準の OLE バリアントが使用され、OLE 文字列 varOleStr は 16 ビットでエンコードされます。それがあなたの観察の理由のようです。

16 ビット テキストへの変換を避けたい場合は、データをバイト配列として入れる必要があります。そうすることで、base64 エンコーディングが無意味になります。ペイロードの base64 エンコードを停止し、バイナリをバイト配列で送信します。

于 2013-11-22T07:28:48.233 に答える
2

質問の例に沿って、これが私がそれを機能させる方法です(私の質問で参照されている別の質問に対するDavidの回答からのコードとコメントを使用して):

function PrepData(StrVal: string; Data: TBytes): OleVariant;
var
  SafeArray: PVarArray;
begin
  Result := VarArrayCreate([0, 1], varVariant);
  Result[0] := StrVal;
  Result[1] := VarArrayCreate([1, Length(Data)], varByte);
  SafeArray := VarArrayAsPSafeArray(Result[1]);
  Move(Pointer(Data)^, SafeArray.Data^, Length(Data));
end;

次に、DataSnap サーバーで、次のように OleVariant からバイナリ データを抽出できます。これは、OleVariantのバリアント配列からのものであると想定しますValueResult[1]

procedure GetBinaryData(Value: Variant; Result: TMemoryStream);
var
  SafeArray: PVarArray;
begin
  SafeArray := VarArrayAsPSafeArray(Value);
  Assert(SafeArray.ElementSize=1);
  Result.Clear;
  Result.WriteBuffer(SafeArray.Data^, SafeArray.Bounds[0].ElementCount);
end;
于 2013-11-22T09:22:13.867 に答える