C#:编组包含数组一个struct(C#: marshalling a struct that co

2019-07-18 18:53发布

我做了一些C#互操作工作。 我有以下结构:

#pragma pack(push,1)
typedef struct
{
    unsigned __int64 Handle;
    LinkType_t Type;
    LinkState_t State;
    unsigned __int64 Settings;
    signed __int8 Name[MAX_LINK_NAME];
    unsigned __int8 DeviceInfo[MAX_LINK_DEVINFO];
    unsigned __int8 Reserved[40];
} LinkInfo_t;

这是我尝试将其转换成一个C#的结构:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LinkInfo_t
{
    [MarshalAs(UnmanagedType.U8)]
    public UInt64 Handle;
    MarshalAs(UnmanagedType.I4)]
    public LinkType_t Type;
    [MarshalAs(UnmanagedType.I4)]
    public LinkState_t State;
    [MarshalAs(UnmanagedType.U8)]
    public UInt64 Settings;
    [MarshalAs(UnmanagedType.LPStr, SizeConst = MAX_LINK_NAME)]
    public string Name;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_LINK_DEVINFO, ArraySubType = UnmanagedType.U1)]
    public byte[] DeviceInfo;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40, ArraySubType = UnmanagedType.U1)]
    public byte[] Reserved;
}

但是,每当我初始化结构的名称,DeviceInfo,并保留字段都设置为null。 我该如何解决?

Answer 1:

对于数组,尽量使用fixed关键字:

public fixed byte DeviceInfo[MAX_LINK_DEVINFO];
public fixed byte Reserved[40];


Answer 2:

每当我初始化结构的名称,DeviceInfo,并保留字段都设置为null

这是正确的,你的定义看起来OK我(顺便说一句,你不需要[MarshalAs]在原始字段的默认行为是你指定什么有做的)。 因为你的阵列字段null ,编组你的结构非托管内存时,封送什么都不会做他们,但它要创建的字符串,解编时阵列。



Answer 3:

什么安东Tykhyy说是正确的。 我只是想用一些例子来阐明。 使用“固定”的作品,但强迫你使用“不安全”为好。 我想避免使用不安全尽可能。 使用元帅是一个办法让周围。

首先,让我们说,我有一个用C以下定义创建的库。

typedef struct {
    int messageType;
    BYTE payload[60];
} my_message;

/**
* \param[out] msg    Where the message will be written to
*/
void receiveMessage(my_message *msg);

/*
* \param[in] msg    The message that will be sent
*/
void sendMessage(my_message *msg);

在C#,以下结构将等效于一个在C.

[StructLayout(LayoutKind.Sequential, Size = 64), Serializable]
struct my_message
{
    int messageType;
    [MarshalAs(UnmanagedType.ByValArray,SizeConst = 60)]
    byte[] payload;

    public initializeArray()
    {
        //explicitly initialize the array
        payload = new byte[60];
    }
}

由于receiveMessage味精()记录为[OUT],你不需要把它传递给函数之前做什么特别在结构数组。 即:

my_message msg = new my_message();
receiveMessage(ref msg);
byte payload10 = msg.payload[10];

由于的sendMessage味精()记录为[中],则需要调用函数之前,填补了数组。 填充阵列之前,该阵列需要使用它之前被明确实例化。 即:

my_message msg = new my_message();
msg.initializeArray();
msg.payload[10] = 255;
sendMessage(ref msg);

调用initializeArray()应该实例在结构这个阵列中创建以前分配的空间阵列。



文章来源: C#: marshalling a struct that contains arrays