从Delphi DLL发送二进制数据到C#应用程序

从Delphi DLL发送二进制数据到C#应用程序,c#,delphi,pinvoke,delphi-2010,C#,Delphi,Pinvoke,Delphi 2010,我有一个Delphi 2010 DLL,用于压缩C#应用程序中的一些数据。DLL函数如下所示: function CompressString(aInputString: PAnsiChar; aInputStringSize: Integer; var aOutPutString: PAnsiChar; var aOutPutStringSize: Integer; var aErrorMsgBuffer: PAnsiChar; var aErrorMsgBufferSize: i

我有一个Delphi 2010 DLL,用于压缩C#应用程序中的一些数据。DLL函数如下所示:

function CompressString(aInputString: PAnsiChar; aInputStringSize: Integer; 
  var aOutPutString: PAnsiChar; var aOutPutStringSize: Integer; 
  var aErrorMsgBuffer: PAnsiChar; var aErrorMsgBufferSize: integer): Integer; 
  stdcall; export;
[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);
function CompressByteArray(
  InputBuffer: PByte;
  InputBufferLength: Integer;
  OutputBuffer: PByte;
  var OutputBufferLength: Integer;
  out ErrorMsg: WideString
): Integer; stdcall;
C#方法如下所示:

function CompressString(aInputString: PAnsiChar; aInputStringSize: Integer; 
  var aOutPutString: PAnsiChar; var aOutPutStringSize: Integer; 
  var aErrorMsgBuffer: PAnsiChar; var aErrorMsgBufferSize: integer): Integer; 
  stdcall; export;
[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);
function CompressByteArray(
  InputBuffer: PByte;
  InputBufferLength: Integer;
  OutputBuffer: PByte;
  var OutputBufferLength: Integer;
  out ErrorMsg: WideString
): Integer; stdcall;
我的问题是,
aOutPutString
被截断,C#App只看到部分数据。如果我将Delphi DLL中的
aOutPutString
更改为一个简单的文本常量(仅用于测试),它就可以正常工作

在DLL中,我正在处理字符串。在函数的末尾,我调用:

StrPCopy(aOutPutString, vOutOutAnsiStr);
转换
AnsiString
do
PAnsiChar


我想我不应该使用
PAnsiChar
而是一个
字节数组
,但我不知道如何做到这一点。

既然你真的在使用字节数组,我会在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
,但是您更愿意使用字节数组。我会在Delphi端使用
PByte
,函数如下所示:

function CompressString(aInputString: PAnsiChar; aInputStringSize: Integer; 
  var aOutPutString: PAnsiChar; var aOutPutStringSize: Integer; 
  var aErrorMsgBuffer: PAnsiChar; var aErrorMsgBufferSize: integer): Integer; 
  stdcall; export;
[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);
function CompressByteArray(
  InputBuffer: PByte;
  InputBufferLength: Integer;
  OutputBuffer: PByte;
  var OutputBufferLength: Integer;
  out ErrorMsg: WideString
): Integer; stdcall;

对于错误消息文本,我使用了
WideString
marshallas(EnumeratedType.BStr)
来简化内存分配。由于共享COM堆分配了一个
BSTR
,因此可以在Delphi代码中将其作为
WideString
分配,然后在边界的另一侧正确地解除分配。

使用PAnsiChar使字符串在第一个“0”字节处截断

您可以使用两个out参数,而不是类型为
PAnsiChar
的out参数:一个是指向字节数组的指针,另一个是包含数组大小的整数


一旦以后需要访问DLL,就必须小心不要释放DLL上的数组。在C端,在外部函数声明中,您将捕获指针为
IntPtr
,并使用
Marshal.Copy
方法将内容复制到C字节数组。

字符串在压缩/序列化意义上与“binary”不是同义词。。。使用byte[]可能会更好,我完全同意,但我不知道如何做到这一点。你能举个例子吗?对不起,我已经十多年没有接触过Delphi/Pascal了。@Marc同意,
byte[]
似乎是最自然的。