Прекарах по-голямата част от вчера, опитвайки се да разреша този проблем като по-голяма част от въпроса за „Представяне на обединени битови полета с помощта на 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 не го прави.
- Уверете се, че спазвате „endianness“ на целочислените си типове данни
- Избягвайте, ако изобщо е възможно, каквито и да било връзки с основния език, т.е. избягвайте мениджъра на езиковата памет - придържайте се към "обикновени стари типове данни". Това ще направи маршалинга на данни по кабела много по-прост.
person
Stacy Dudovitz
schedule
24.11.2018