2015-10-05 2 views
1

Я пытаюсь сериализации следующую C# структуру:сортировочных на 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)].

Is [MarshalAs (UnmanagedType.U1)] unmarshallable? что я делаю?

+0

U1 - один байт, а числа, которые вы используете, больше 256. U4 представляет собой четырехбайтовое целое число, которое может обрабатывать ваши большие числа. – jdweng

+0

Благодаря @jdweng модель данных предназначена для привязки к спецификации API с образцами данных, которые вы видите в фрагменте кода. –

+0

Размер = 70, когда у него есть член, который принимает 182 байта, абсолютно не имеет никакого смысла. Что-то очень, очень неправильно с «спецификацией». Используйте телефон. –

ответ

2

Проблема заключается в том, что определение:

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

неоднозначна относительно того, что размер может быть членами. Если маркер interop использует размер члена, он рассчитает 4 байта, тогда как если он использует атрибут MarshalAs, он рассчитает 1 байт. Изменение элемента для использования правильного размера,

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

должен исправить проблему.

0

Итак, после принятия рекомендации @ B объявить типы данных 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(); 
    } 
} 
+0

Не забудьте принять ответ от Б. –

Смежные вопросы