2015-09-19 2 views
0

VB.NET 4.5Как избежать избыточного байта, когда структура содержит байтовую переменную? (VB.NET)

У меня есть структура, которая содержит один байт. Мне нужно получить массив байтов, который будет отправлен через последовательный порт.

Public Structure ExampleStructure 
    Public variable1 As Byte 
    Public variable2 As UInt16 
    Public variable3 As UInt16 

    Public Function getBytes() As Byte() 
     Dim binaryBytes(5) As Byte 
     Dim pointerCommand As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Me)) 
     Marshal.StructureToPtr(Me, pointerCommand, False) 
     Marshal.Copy(pointerCommand, binaryBytes, 0, Marshal.SizeOf(Me)) 
     Marshal.FreeHGlobal(pointerCommand) 
     Return binaryBytes 
    End Function 
End Structure 

Этот вопрос:

, когда я использую Marshal.AllocHGlobal, Marshal.StructureToPtr и Marshal.Copy массив байт Возвращается 6 байт. .NET создает 2 байта для переменной1, поэтому имеется избыточный байт между данными переменной1 и переменной2.

Я могу решить эту проблему с помощью LayoutKind.Explicit и определения FieldOffsets.

<StructLayout(LayoutKind.Explicit)> _ 
Public Structure ExampleStructure 
    <FieldOffset(0)> Public variable1 As Byte 
    <FieldOffset(1)> Public variable2 As UInt16 
    <FieldOffset(3)> Public variable3 As UInt16 

    Public Function getBytes() As Byte() 
     Dim binaryBytes(5) As Byte 
     Dim pointerCommand As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Me)) 
     Marshal.StructureToPtr(Me, pointerCommand, False) 
     Marshal.Copy(pointerCommand, binaryBytes, 0, Marshal.SizeOf(Me)) 
     Marshal.FreeHGlobal(pointerCommand) 
     Return binaryBytes 
    End Function 
End Structure 

Теперь, когда я получаю байты, больше нет избыточного байта между переменной1 и переменной2.

Это похоже на неуклюжий способ сделать это. Есть ли лучший вариант, когда мне не нужно вручную устанавливать FieldOffsets? Эта структура проста, но они могут стать намного более сложными.

+0

компилятор пытается оптимизировать код, совместив данные на 16-битной границе. Таким образом, вы боретесь с оптимизатором компилятора. В наши дни микропроцессоры работают быстрее, когда коды выровнены по более широким границам. Не уверен, есть ли опция компилятора для принудительного выравнивания кода на границах байтов. Попробуйте: LayoutKind.Sequential – jdweng

+0

Я просто попробовал LayoutKind.Sequential, но не повезло. – user2347261

+0

Try pack option: [StructLayout (LayoutKind.Sequential, Pack = 8)] – jdweng

ответ

0

Исправление было очень просто - нужно добавить тег LayoutKind.Sequential, пакет: = 1

<StructLayout(LayoutKind.Sequential, Pack:=1)> _ 
Public Structure ExampleStructure 
    Public variable1 As Byte 
    Public variable2 As UInt16 
    Public variable3 As UInt16 

    Public Function getBytes() As Byte() 
     Dim binaryBytes(5) As Byte 
     Dim pointerCommand As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Me)) 
     Marshal.StructureToPtr(Me, pointerCommand, False) 
     Marshal.Copy(pointerCommand, binaryBytes, 0, Marshal.SizeOf(Me)) 
     Marshal.FreeHGlobal(pointerCommand) 
     Return binaryBytes 
    End Function 
End Structure