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

发布于 2024-12-12 17:09:39 字数 423 浏览 1 评论 0原文

如何将 Delphi 代码转换为 C# 代码?它需要一个字节数组,但我不确定 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);

How do I convert the Delphi code into C#? It takes an array of Byte, but I'm not sure what the C# equivalent is. My attempt doesn't work and throws exceptions like 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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浸婚纱 2024-12-19 17:09:39

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

然而,您可以欺骗 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 的数组是否合适,或者您是否真的想要只需将第二项设置为非零值即可。

A Delphi open array is not a valid interop type. You can't easily match that up with a C# byte[] through a P/invoke. In an ideal world a different interface would be exposed by the native DLL but as you have stated in comments, you do not have control over that interface.

However, you can trick the C# code into passing something that the Delphi DLL will interpret correctly, but it's a little dirty. The key is that a Delphi open array declared like that has an extra implicit parameter containing the index of the last element in the array.

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

To be clear, in spite of the parameter lists looking so different, the C# code above will successfully call the Delphi DLL function declared so:

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

I have no idea whether or not passing an array of length 5 is appropriate, or whether you really meant to just set the second item to a non-zero value.

心头的小情儿 2024-12-19 17:09:39

这就是我如何成功实现从 Delphi & 向 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 也带有数组参数(Delphi 的 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++)

The same in delphi will如果

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

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

This is the way how I implemented successfully sending arrays from and to 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
);

Note that single types have REF and arrays DO NOT HAVE REF, but arrays will still work like REF anyway

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;

Note that VAR is also with Array parameters (Delphi analog of REF).

I had all sorts of errors, because I had ref with arrays in C# code

Another problem that caused memory corruption for me was that I did not notice that these codes are not the same in Delphi and C#:

Delphi:

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

C#

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

The same in delphi would be

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

If you overflow boundaries of arrays passed to delphi it could also cause all sorts of errors

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文