C#: marshalling a struct that contains arrays

前端 未结 3 1667
伪装坚强ぢ
伪装坚强ぢ 2021-01-02 21:25

I am doing some C# interop work. I have the following struct:

#pragma pack(push,1)
typedef struct
{
    unsigned __int64 Handle;
    LinkType_t Type;
    Lin         


        
相关标签:
3条回答
  • 2021-01-02 21:29

    For the arrays, try to use the fixed keyword:

    public fixed byte DeviceInfo[MAX_LINK_DEVINFO];
    public fixed byte Reserved[40];
    
    0 讨论(0)
  • 2021-01-02 21:30

    What Anton Tykhyy says is correct. I just want to clarify with some examples. Using 'fixed' works, but that forces you to use 'unsafe' as well. I like to avoid using unsafe wherever possible. Using Marshal is a way to get around that.

    First, let's say that I have a library that was created in C with the following definitions.

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

    In C#, the following structure would be equivalent to the one in 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];
        }
    }
    

    Since the msg in receiveMessage() is documented as [out], you don't need to do anything special to the array in the structure before passing it to the function. i.e.:

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

    Since the msg in sendMessage() is documented as [in], you will need to fill the array before calling the function. Before filling the array, the array needs to be explicitly instantiated before using it. i.e.:

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

    Calling initializeArray() should instantiate the array in the previously allocated space created within the struct for this array.

    0 讨论(0)
  • 2021-01-02 21:36

    whenever I initialize the struct the Name, DeviceInfo, and Reserved fields are all set to null

    This is correct, and your definition looks OK to me (BTW, you don't need [MarshalAs] on the primitive fields, the default behaviour is to do what you specified there). Because your array fields are null, the marshaler won't do anything about them when marshaling your struct to unmanaged memory, but it's going to create the strings and arrays when unmarshaling.

    0 讨论(0)
提交回复
热议问题