【问题标题】:How do I use C# to call a function that receives a Delphi open-array parameter?如何使用 C# 调用接收 Delphi 开放数组参数的函数?
【发布时间】:2011-10-30 10:39:53
【问题描述】:

如何将 Delphi 代码转换为 C#?它需要一个array of Byte,但我不确定 C# 等价物是什么。我的尝试不起作用,并引发了 AccessViolationException 之类的异常。

德尔福:

function SetLevel(a: array of byte): boolean; stdcall; external 'DMX510.dll';

C#:

[DllImport("DMX510.DLL")]
public static extern Boolean SetLevel(Byte[] bytearray);

Byte[] byteArray = new Byte[5];
byteArray[1] = 75;
SetLevel(byteArray);

【问题讨论】:

  • monacor.de/fileadmin/user_upload/software_updates/DMX510dll.zip 这是带有一些delphi示例代码的dll的链接
  • DLL 用于控制 USB-DMX 控制器。这个控制器让我可以从我的笔记本电脑上控制我的照明和激光硬件。 DMX 是一个串行总线系统,该阵列用于输出 0 到 255 到 510 个硬件通道之间的值,每个通道用于一个单独的设备。设备是字节数组索引,值是DMX值。
  • 示例中的源代码和 cmets 显示最多有 510 个通道。字节数组为此做好了准备;创建表单时,它的长度为 510,并且所有字节都初始化为 0。现在,我仍然不知道如何将 C# 数组映射到 Delphi 数组(如果这种方式可能的话),但我可以想象为什么一个 5 的数组会给你一个访问冲突。

标签: c# delphi pinvoke


【解决方案1】:

Delphi 开放数组不是有效的互操作类型。您无法通过 P/invoke 轻松地将其与 C# byte[] 匹配。在理想情况下,本地 DLL 会公开不同的接口,但正如您在 cmets 中所述,您无法控制该接口。

但是,您可以欺骗 C# 代码传递一些 Delphi DLL 可以正确解释的内容,但这有点脏。关键是这样声明的 Delphi 开放数组有一个额外的隐式参数,其中包含数组中最后一个元素的索引。

[DllImport(@"DMX510.DLL")]
public static extern bool SetLevel(byte[] byteArray, int high);

byte[] byteArray = new byte[] { 0, 75, 0, 0, 0};
SetLevel(byteArray, byteArray.Length-1);

需要明确的是,尽管参数列表看起来如此不同,但上面的 C# 代码将成功调用如此声明的 Delphi DLL 函数:

function SetLevel(a: array of byte): boolean; stdcall;

我不知道传递长度为 5 的数组是否合适,或者您是否真的打算将第二项设置为非零值。

【讨论】:

  • 对于它的价值,当从 C++ 创建的库中访问数组到 Delphi 中时,您也需要使用此方法。如果您有权访问源代码,另一种方法是使用 COM 安全数组导出数组。
【解决方案2】:

这就是我成功实现在 Delphi 和 C# 之间发送数组的方式。

C#:

[DllImport("Vendors/DelphiCommunication.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void LoadFromFileCHR(
    string sFileName,
    ref int iSize,
    ref double AreaCoef,
    ref double FWaveLength,
    ref bool FHasWaveLength,
    double[] ChromX,
    double[] ChromY
);

请注意,单一类型有 REF数组没有 REF,但数组仍然无论如何都像 REF 一样工作

德尔福:

Type    
    ArrayDouble100k = array [0..99999] of Double;

procedure LoadFromFileCHR(
    FileName : String;
    var Size : Integer;
    var AreaCoef : Double;
    var FWaveLength: Double;
    var FHasWaveLength : Boolean;
    var ChromX : ArrayDouble100k;
    var ChromY : ArrayDouble100k); StdCall;
begin
   //...
end;

exports LoadFromFileCHR;

请注意,VAR 也带有数组参数(Delphi 类似 REF)。

我遇到了各种各样的错误,因为我在 C# 代码中使用数组进行了 ref

另一个导致我内存损坏的问题是我没有注意到这些代码在 Delphi 和 C# 中是不一样的:

德尔福:

for i := 0 to Length(fileCHR.ChromX) do //This is wrong

C#

for(int i = 0; i < fileCHR.ChromX.Length; i++)

delphi 中也是这样的

for i := 0 to Length(fileCHR.ChromX) - 1 do //This is right

如果你溢出传递给 delphi 的数组的边界,它也可能导致各种错误

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 2019-01-22
    相关资源
    最近更新 更多