如何使用C#调用接收Delphi开放数组参数的函数?

时间:2011-10-30 10:39:53

标签: c# delphi pinvoke

如何将Delphi代码转换为C#?需要array of Byte,但我不确定C#的等价物是什么。我的尝试不起作用并抛出像AccessViolationException这样的异常。

的Delphi:

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

2 个答案:

答案 0 :(得分:8)

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

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

[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的数组是否合适,或者你是否真的想将第二项设置为非零值。

答案 1 :(得分:0)

这是我成功实现从Delphi和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一样工作

的Delphi:

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也使用数组参数(德尔福模拟REF)。

我有各种各样的错误,因为我在C#代码中使用了数组

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

的Delphi:

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的数组的边界,它也可能导致各种错误