簡體   English   中英

編組C#結構

[英]Marshalling a C# structure

我正在嘗試序列化以下c#結構:

[Serializable]
[StructLayout(LayoutKind.Sequential, Size = 70, CharSet = CharSet.Ansi)]
public struct USSDContinueModel
{
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Length;

    [MarshalAs(UnmanagedType.U4)]
    public uint Command_ID;

    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Status;

    [MarshalAs(UnmanagedType.U4)]
    public uint Sender_ID;

    [MarshalAs(UnmanagedType.U4)]
    public uint Receiver_ID;

    [MarshalAs(UnmanagedType.U1)]
    public uint Ussd_Version;

    [MarshalAs(UnmanagedType.U1)]
    public uint Ussd_Op_Type;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string MsIsdn;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string Service_Code;

    [MarshalAs(UnmanagedType.U1)]
    public uint Code_Scheme;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 182)]
    public string Ussd_Content;

    // Calling this method will return a byte array with the contents
    // of the struct ready to be sent via the tcp socket.
    public byte[] Serialize()
    {
        // allocate a byte array for the struct data
        var buffer = new byte[Marshal.SizeOf(typeof(USSDContinueModel))];

        // Allocate a GCHandle and get the array pointer
        var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        var pBuffer = gch.AddrOfPinnedObject();

        // copy data from struct to array and unpin the gc pointer
        Marshal.StructureToPtr(this, pBuffer, false);
        gch.Free();

        return buffer;
    }

    // this method will deserialize a byte array into the struct.
    public void Deserialize(ref byte[] data)
    {
        var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
        this = (USSDContinueModel)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(USSDContinueModel));
        gch.Free();
    }
}

當我嘗試序列化該結構的實例時,請說:

        public USSDContinueModel continueModel;
        continueModel.Command_Length = 174;
        continueModel.Command_ID = 0x00000070;
        continueModel.Command_Status = 0;
        continueModel.Sender_ID = 0x01000005;
        continueModel.Receiver_ID = 0x2900AB12;
        continueModel.Ussd_Version = 0x20;
        continueModel.Ussd_Op_Type = 0x01;
        continueModel.MsIsdn = "08098765476";
        continueModel.Service_Code = "*308";
        continueModel.Code_Scheme = 0x44;
        continueModel.Ussd_Content = "1. Continue if you are 18+ 2. Exit i";

我不斷收到錯誤“類型:USSDcontinueModel無法編組為非托管結構;無法計算出有意義的大小或偏移量”。

我注意到當我將Ussd_Version,Ussd_Op_Type和Code_Scheme設置為[MarshalAs(UnmanagedType.U1)]時會發生這種情況,但是它與[MarshalAs(UnmanagedType.U4)]可以很好地工作。

[MarshalAs(UnmanagedType.U1)]是否不可編組? 我該怎么辦?

問題在於定義:

[MarshalAs(UnmanagedType.U1)]
public uint Ussd_Op_Type;

關於成員的大小不確定。 如果互操作元帥使用成員的大小,它將計算4個字節,而如果使用MarshalAs屬性,它將計算1個字節。 更改成員以使用正確的尺寸類型,

[MarshalAs(UnmanagedType.U1)]
public byte Ussd_Op_Type;

應該解決這個問題。

因此,在采納@theB的建議之后,將U1數據類型聲明為字節。 問題已解決。 更新后的結構定義如下:

[Serializable]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
public struct USSDContinueModel
{
    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Length;

    [MarshalAs(UnmanagedType.U4)]
    public uint Command_ID;

    [MarshalAs(UnmanagedType.U4)]
    public uint Command_Status;

    [MarshalAs(UnmanagedType.U4)]
    public uint Sender_ID;

    [MarshalAs(UnmanagedType.U4)]
    public uint Receiver_ID;

    [MarshalAs(UnmanagedType.U1)]
    public byte Ussd_Version;

    [MarshalAs(UnmanagedType.U1)]
    public byte Ussd_Op_Type;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string MsIsdn;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
    public string Service_Code;

    [MarshalAs(UnmanagedType.U1)]
    public byte Code_Scheme;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 182)]
    public string Ussd_Content;

    // Calling this method will return a byte array with the contents
    // of the struct ready to be sent via the tcp socket.
    public byte[] Serialize()
    {
        // allocate a byte array for the struct data
        var buffer = new byte[Marshal.SizeOf(typeof(USSDContinueModel))];

        // Allocate a GCHandle and get the array pointer
        var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        var pBuffer = gch.AddrOfPinnedObject();

        // copy data from struct to array and unpin the gc pointer
        Marshal.StructureToPtr(this, pBuffer, false);
        gch.Free();

        return buffer;
    }

    // this method will deserialize a byte array into the struct.
    public void Deserialize(ref byte[] data)
    {
        var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
        this = (USSDContinueModel)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(USSDContinueModel));
        gch.Free();
    }
}

暫無
暫無

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

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