简体   繁体   中英

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:

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:

    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?

You might need to specify the packing of the struct (depending on the default packing used by the C++ code). You can also specify a fixed-sized array for the marshalling to take care of using [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.

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.

With these changes, the Marshaller should take care of things for you.

The C/C++ struct is more like a "fixed buffer":

    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.

I'm not 100% sure, but I believe you should also use an unmanaged pointer in the P/Invoke layer:

public static extern int mvb_PutPort(MyStruct* CommData);

which means you need to call it via:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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