【问题标题】:Send binary data from a Delphi DLL do a C# App从 Delphi DLL 发送二进制数据做一个 C# 应用程序
【发布时间】:2025-11-27 20:55:02
【问题描述】:

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

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

StrPCopy(aOutPutString, vOutOutAnsiStr);

要转换AnsiString,请执行PAnsiChar

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

【问题讨论】:

  • 字符串在压缩/序列化意义上不是“二进制”的同义词......这可能会更好地使用 byte[]
  • 我完全同意,但我不知道该怎么做。可以举个例子吗?
  • 抱歉,我已经十多年没有接触过 Delphi/Pascal 了。
  • @Marc 同意,byte[] 似乎是最自然的。

标签: c# delphi pinvoke delphi-2010


【解决方案1】:

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

    在 Delphi 方面,您当前使用的是PAnsiChar,但您更愿意使用字节数组。然后我会在 Delphi 端使用PByte,函数看起来像这样:

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

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

    【讨论】:

      最近更新 更多