Я потратил большую часть вчерашнего дня, пытаясь решить эту проблему как большую часть проблемы «Представления битовых полей объединения с использованием StrucLayout и FieldOffset в c #», которая не только ответит на ваш вопрос (см. Выше), но может быть найдена здесь. :
Представление битовых полей объединения с использованием StrucLayout и FieldOffset в c #
По сути, вам нужно определить структуру (тип значения) и использовать объект BitVector32 , чтобы определить секцию битового поля для каждого битового поля, которое вы хотите представить. Вы можете пропустить часть о союзе, поскольку это не относится к вашему вопросу, но большая часть поста по-прежнему относится к вашему вопросу.
Просто для удовольствия, я подумал, что я бы подстроил структуру C # для вашего примера RGB16:
Примечание. Объект BitVector32 имеет длину 32 бита, поэтому значение 16 в прозвище вводит в заблуждение ... обратите внимание на это
[StructLayout(LayoutKind.Explicit, Size = 1, CharSet = CharSet.Ansi)]
public struct Rgb16
{
#region Lifetime
/// <summary>
/// Ctor
/// </summary>
/// <param name="foo"></param>
public Rgb16(int foo)
{
// allocate the bitfield
buffer = new BitVector32(0);
// initialize bitfield sections
r = BitVector32.CreateSection(0x0f); // 4
g = BitVector32.CreateSection(0x1f, r); // 5
b = BitVector32.CreateSection(0x0f, g); // 4
}
#endregion
#region Bifield
// Creates and initializes a BitVector32.
[FieldOffset(0)]
private BitVector32 buffer;
#endregion
#region Bitfield sections
/// <summary>
/// Section - Red
/// </summary>
private static BitVector32.Section r;
/// <summary>
/// Section - Green
/// </summary>
private static BitVector32.Section g;
/// <summary>
/// Section - Blue
/// </summary>
private static BitVector32.Section b;
#endregion
#region Properties
/// <summary>
/// Flag 1
/// </summary>
public byte R
{
get { return (byte)buffer[r]; }
set { buffer[r] = value; }
}
/// <summary>
/// Flag 2
/// </summary>
public byte G
{
get { return (byte)buffer[g]; }
set { buffer[g] = value; }
}
/// <summary>
/// Flag 1
/// </summary>
public byte B
{
get { return (byte)buffer[b]; }
set { buffer[b] = value; }
}
#endregion
#region ToString
/// <summary>
/// Allows us to represent this in human readable form
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"Name: {nameof(Rgb16)}{Environment.NewLine}Red: {R}: Green: {G} Blue: {B} {Environment.NewLine}BitVector32: {buffer}{Environment.NewLine}";
}
#endregion
}
Чтобы использовать это, вы должны выделить следующее:
internal static class Program
{
/// <summary>
/// Main entry point
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
var rgb16 = new Rgb16(0)
{
R = 24,
G = 16,
B = 42
};
Также, пожалуйста, обратите внимание, что есть ссылка на это:
Битовые поля в C #
Здесь есть много других ответов, но у них есть много подводных камней, о которых нужно знать. Пожалуй, лучшее, что я могу сделать здесь, это просто перечислить то, что вы можете искать:
- Обязательно упакуйте свои данные на границе байтов
- Обязательно укажите размер типов данных, т. Е. int изменяет размер в зависимости от аппаратного обеспечения, System.Int32 не изменяет.
- Убедитесь, что вы соблюдаете порядковый номер ваших целочисленных типов данных
- Избегайте, если это вообще возможно, каких-либо связей с базовым языком, то есть избегайте менеджера языковой памяти - придерживайтесь "простых старых типов данных". Это значительно упростит маршалинг данных по сети.