簡體   English   中英

將嵌套結構編組到C#

[英]Marshalling nested structs to C#

我們有COM服務器(作為dll,我們只有dll文件),它實現了兩個COM接口。 接口之一允許我們從某些設備獲取消息(作為結構)。 根據消息,我們需要處理相應的結構。 每個結構都指向結構VARIANT的指針。 此結構的類型為字節數組(VT_ARRAY | VT_UI1)

所有結構都包含結構Header和其他一些信息。 結構Header包含字段MsgId 根據MsgId我們需要處理其他結構。

為了將結構從dll轉換為c#,我們使用反射。

現在是時候了:

// Header (sub-struct of main struct) - 
[StructLayout(LayoutKind.Sequential)]
public struct Header
{
    public int MsgId;
} 

// main struct
[StructLayout(LayoutKind.Sequential)]
public struct Main
{
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct)]
    public Header h;
    public int count;
}

每隔100毫秒,我們就會通過反射從設備獲取數據:

   private bool ReadMessage(ref object msg)
    {
        object _msg = null;
        object[] args = new Object[] { _msg };

        ParameterModifier byRefParamMod = new ParameterModifier(1);

        byRefParamMod[0] = true;

        ParameterModifier[] pmArray = { byRefParamMod };

        var value = SomeWrapper.CallMethod(ClientInstance, "ReadMessage", args, pmArray);

        msg = args[0];

        return ((int)value == S_OK) ? true : false;
    }

然后我們將msgbyte[] ,然后需要將字節數組轉換為結構。 在這個地方,封送處理有些問題。

正如我寫的那樣,為了定義我們需要處理的結構(換句話說, 我們需要封送處理 ),首先,我們需要整理所有結構中包含的Header結構(換句話說,來自device的所有消息中的字形 )。

為了編組Header結構,我們使用結構中的C#數組中建議的方法(進行一些編輯):

 public static T DeserializeMsg<T>(byte[] msg) where T : struct
    {
        // Pin the managed memory while, copy it out the data, then unpin it
        GCHandle handle = GCHandle.Alloc(msg, GCHandleType.Pinned);
        T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
        handle.Free();

        return theStructure;
    }

我們如何使用一個:

 private void ProcessMessage(byte[] message)
 {
     Header msgHeader = new Header();
     msgHeader = DeserializeMsg<Header>(message);
 }

一切都好! 在這里,我們得到msgHeader.MsgId ,然后我們需要得到另一個結構:

private void ProcessMessage(byte[] message)
{
    Header msgHeader = new Header();
    msgHeader = DeserializeMsg<Header>(message);

    switch (msgHeader.MsgId)
    {
        case START:            
        Main msgMain = new Main();
        // Here we get exception (see below)
        msgMain = DeserializeMsg<Main>(message);            
        break;
        default:
        break;
    }
}

在這里,我們得到了例外: 無法封送類型為“ Main”的字段“ h”。 無效的托管/非托管類型組合(此值類型必須與Struct配對)

我們試圖將內部結構h MarshalAsAttribute聲明更改為

[MarshalAsAttribute(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_SAFEARRAY)]

[MarshalAsAttribute (UnmanagedType.SafeArray, SafeArrayUserDefinedSubType=typeof(Header))]

但它不起作用。 如果可能的話,我們如何從Main結構中獲取數據?

現在,通過BinaryReading 逐字節讀取是我的解決方案。 一切正常。 謝謝大家!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM