简体   繁体   English

在 C# 中将结构指针作为参数传递

[英]Passing a struct pointer as paramater in C#

I need to include a .dll which contains the following C/C++ function prototype and struct definition:我需要包含一个 .dll,其中包含以下 C/C++ 函数原型和结构定义:

typedef struct
{
    unsigned short us1;
    unsigned short us2;
    unsigned short data[16];
} myStruct;
int myFunc(myStruct *MYSTRUCT);

To use this Function i created a new Class:为了使用这个函数,我创建了一个新类:

static class DLL
{
public struct MyStruct
    {
     public ushort us1;
     public ushort us2; 
     public ushort[] data;
     public PDPORT(ushort[] temp1, ushort temp2, ushort temp3)
     {
         us1 = temp2;
         us2 = temp3;
         data = temp1;
     }
    };
    [DllImport("PDL65DLL.dll")]
    public static extern int mvb_PutPort(ref MyStruct CommData);
}

In my main class I initiliaze the struct variable and call the Function like that:在我的主类中,我初始化 struct 变量并像这样调用函数:

    DLL.MyStruct communicationData = new DLL.MyStruct(new ushort[16], new ushort(), new ushort());
             DLL.MyFunc( ref communicationData);

However, this does not seem to work.但是,这似乎不起作用。 The Function is passing something but not the right values, I suggest it is something with the pointer usage.函数正在传递一些东西但不是正确的值,我建议它与指针使用有关。 Maybe a struct* is not the same as ref struct... Can someone explain what the problem is?也许 struct* 与 ref struct 不一样......有人可以解释问题是什么吗?

You might need to specify the packing of the struct (depending on the default packing used by the C++ code).您可能需要指定结构的包装(取决于 C++ 代码使用的默认包装)。 You can also specify a fixed-sized array for the marshalling to take care of using [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] .您还可以使用[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]为编组指定固定大小的数组。

You also don't need the C# implementation to use a struct and indeed for the fairly large size of the data I would recommend using a class.您也不需要 C# 实现来使用struct ,对于相当大的数据,我建议使用类。

Here's an example:下面是一个例子:

[StructLayout(LayoutKind.Sequential, Pack=4)]
public sealed class MyStruct
{
    public ushort   us1;
    public ushort   us2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public ushort[] data;

    public MyStruct(ushort[] temp1, ushort temp2, ushort temp3)
    {
        us1  = temp2;
        us2  = temp3;
        data = new ushort[16];
        Array.Copy(temp1, data, Math.Min(temp1.Length, data.Length));
    }
}

Note how the constructor ensures that the size of the array is correct.请注意构造函数如何确保数组的大小正确。 You must always ensure that the size of the array matches the SizeConst declaration.您必须始终确保数组的大小与SizeConst声明相匹配。

With these changes, the Marshaller should take care of things for you.通过这些更改,Marshaller 应该会为您处理一切事务。

The C/C++ struct is more like a "fixed buffer": C/C++ 结构更像是一个“固定缓冲区”:

    unsafe struct MyStruct
    {
        ushort us1, us2;
        fixed ushort data[16];
    }

This is not the same as an array, and is a little more awkward to work with in the C# code, but: it is possible.这与数组不同,在 C# 代码中使用起来有点尴尬,但是:这是可能的。

I'm not 100% sure, but I believe you should also use an unmanaged pointer in the P/Invoke layer:我不是 100% 确定,但我相信您还应该在 P/Invoke 层中使用非托管指针:

public static extern int mvb_PutPort(MyStruct* CommData);

which means you need to call it via:这意味着您需要通过以下方式调用它:

fixed (MyStruct* ptr = whateverYouWereGoingToPass)
{
    mvb_PutPort(ptr);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM