2012-09-29 18 views
2

我有一个Delphi 2010 DLL将被用于从C#应用程序压缩一些数据。 DLL函数如下:从德尔福DLL发送二进制数据做一个C#应用程序

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#应用程序,只有部分数据被看到。如果我将Delphi DLL中的aOutPutString更改为简单文字常量(仅用于测试),它可以正常工作。

的DLL里面,我处理字符串。在函数的结尾,我称之为:

StrPCopy(aOutPutString, vOutOutAnsiStr); 

要转换AnsiStringPAnsiChar

我想我不应该使用PAnsiChar而是array of byte,但我不知道该怎么做。

+0

字符串是不是在压缩/序列化意义上的“二进制” ......这可能会工作了很多更好的byte [] –

+0

我完全同意的代名词,但我不知道该怎么做。你能举个例子吗? –

+0

对不起,我十多年来没有碰过Delphi/Pascal。 –

回答

6

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

您可以有两个输出参数:一个是指向字节数组的指针,另一个是包含数组大小的整数,而不是具有PAnsiChar类型的输出参数。

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

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 
); 

在德尔福的一面,你正在使用PAnsiChar,而是说你宁愿使用一个字节数组。我对德尔福端使用PByte然后,该函数是这样的:

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

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