2

C# APP から一部のデータを圧縮するために使用される Delphi 2010 DLL があります。DLL 関数は次のようになります。

function CompressString(aInputString: PAnsiChar; aInputStringSize: Integer; 
  var aOutPutString: PAnsiChar; var aOutPutStringSize: Integer; 
  var aErrorMsgBuffer: PAnsiChar; var aErrorMsgBufferSize: integer): Integer; 
  stdcall; export;

C# メソッドは次のようになります。

[DllImport("MyDLL.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi)]
public static extern int CompressString(string aInputString, 
  int aInputStringSize, ref string aOutPutString, 
  out int aOutPutStringSize, ref string aErrorMsgBuffer, 
  out int aErrorMsgBufferSize);

私の問題は、aOutPutString切り捨てられていることです。データの一部のみが C# アプリに表示されています。aOutPutStringDelphi DLL 内を単純なリテラル定数に変更すると (テストのみ)、問題なく動作します。

DLL 内で、文字列を操作しています。関数の最後で、次を呼び出します。

StrPCopy(aOutPutString, vOutOutAnsiStr);

AnsiStringdoを変換しますPAnsiChar

を使用するべきではないと思いますPAnsiCharが、array of byteその方法がわかりません。

4

2 に答える 2

6

PAnsiChar を使用すると、文字列が最初の '0' バイトで切り捨てられます。

type の out パラメーターを使用する代わりに、PAnsiChar2 つの out パラメーターを使用できます。1 つはバイト配列へのポインターであり、もう 1 つは配列のサイズを含む整数です。

後でアクセスする必要がある場合は、DLL の配列を解放しないように注意する必要があります。C# 側では、外部関数宣言でポインターをキャッチしIntPtr、メソッドを使用しMarshal.Copyてコンテンツを C# バイト配列にコピーします。

于 2012-09-29T15:27:16.140 に答える
2

あなたは実際にバイト配列を扱っているので、C# 関数でそのように宣言します。

[DllImport("MyDLL.dll")]
public static extern int CompressByteArray(
    byte[] InputBuffer,  
    int InputBufferLength, 
    byte[] Output, 
    ref int OutputBufferLength, 
    [MarshalAs(UnmanagedType.BStr)]
    out string ErrorMsg
);

Delphi 側では、現在 を使用しPAnsiCharていますが、バイト配列を使用したいと言っています。PByteDelphi 側で使用すると、関数は次のようになります。

function CompressByteArray(
  InputBuffer: PByte;
  InputBufferLength: Integer;
  OutputBuffer: PByte;
  var OutputBufferLength: Integer;
  out ErrorMsg: WideString
): Integer; stdcall;

エラー メッセージのテキストについては、メモリの割り当てを容易にするためにWideStringとを使用しました。MarshalAs(EnumeratedType.BStr)aBSTRは共有 COM ヒープに割り当てられるため、Delphi コードで a として割り当てられWideString、境界の反対側で正しく割り当て解除されます。

于 2012-09-29T14:11:05.713 に答える