Использование перечислений для индексации массива битов - PullRequest
0 голосов
/ 12 августа 2011

Приложение представляет собой основанный на Windows пользовательский интерфейс C # для встроенной системы управления и контроля.

Встроенная система (написанная на C) поддерживает таблицу сбоев, которую она отправляет приложению c #.Таблица неисправностей содержит один бит для каждой неисправности, хранящийся в структуре.Теперь, с точки зрения пользовательского интерфейса, таблица несколько скудна - есть только несколько битов ошибок, которые нас интересуют, поэтому структура может быть представлена ​​следующим образом:Я хочу иметь возможность индексировать каждый интересующий меня бит ошибки. В CI для этого используется перечисление:

typedef enum
{
  FF_PSU1 = offsetof(FAULT_TABLE,PowerSupplyFaults)*8,
  FF_PSU2,
  FF_PSU3, 
  FF_PSU4,
  FF_PSU5,
  FF_PSU6,
  FF_PSU7,
  FF_PSU8,
  FF_PSU9,
  FF_PSU10,
  FF_PSU11,
  FF_PSU12,
  FF_PSU13,

  FF_MACHINERY1 = offsetof(FAULT_TABLE,MachineryFaults)*8,
  FF_MACHINERY2,
  FF_MACHINERY3,
  FF_MACHINERY4,
  FF_MACHINERY5,
  FF_MACHINERY6,
  FF_MACHINERY7,
  FF_MACHINERY8,
  FF_MACHINERY9,
  FF_MACHINERY10,

  FF_COMMS1 = offsetof(FAULT_TABLE,CommunicationFaults)*8,
  FF_COMMS2,
  FF_COMMS3,
  FF_COMMS4,
  FF_COMMS5,
  FF_COMMS6,
  FF_COMMS7,
  FF_COMMS8,
  FF_COMMS9,
  FF_COMMS10,
  FF_COMMS11,
  FF_COMMS12,
  FF_COMMS13
}FAULT_FLAGS;

Есть ли способ создать подобное перечисление на основеструктура данных в C #?

Ответы [ 4 ]

0 голосов
/ 12 августа 2011

Создать перечисление, которое определяет смещение в битах в каждом наборе байтов:

enum PowerSupplyFaults
{
    PowerSupplyFault1, PowerSupplyFault2, PowerSupplyFault3
}

PowerSupplyFault1 будет автоматически назначено 0, Fault2 как 1 и т. Д.

Предполагается, что вы получите структуру, которая отражает версию C:

struct FaultTable
{
    // ...

    public byte[] PowerSupplyFaults;
    public byte[] MachineFaults;

    // ...
}

Вы можете проверить наличие ошибки, подав байты в BitArray и протестировав по индексу:

FaultTable faults = GetFaultTable();
BitArray psu_faults = new BitArray( fault_table.PowerSupplyFaults );

if ( psu_faults[ (int)PowerSupplyFaults.PowerSupplyFault3 ] )
{
    // ...
}

Кроме того, вы можете пройтись по всем битам и посмотреть, какие из них установлены:

for ( int i = 0; i < psu_faults.Length; i++ )
{
    if ( psu_faults[ i ] )
    {
        Console.WriteLine( "PSU fault: {0}", (PowerSupplyFaults)i );
    }
}
0 голосов
/ 12 августа 2011

Вы можете получить смещение элемента структуры с помощью Marshal.OffsetOf

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.offsetof.aspx

Ваша структура может быть создана почти таким же образом, хотя вы должны убедиться, что выукажите макет (хотя я предполагаю, что это зависит от того, как создается экземпляр структуры).

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute(v=vs.71).aspx

Однако ... проблема возникнет с Enum.Перечисляемые значения должны быть константами времени компиляции, а Marshal.OffsetOf - нет.Поэтому вам, возможно, придется хранить смещения в качестве статических членов класса.

Я также думаю, что вам, вероятно, придется отклониться от небезопасного кода, чтобы реально использовать эти смещения, как только они у вас есть -вероятно, это лучший способ приблизиться к тому, что вы хотите сделать в управляемом коде.

0 голосов
/ 12 августа 2011

Вы можете создать enum для отображения битов / флагов, но вы не можете отобразить более 32 бит.

В вашем примере я бы создал несколько констант long (64 бита).Это не решит ограничение по битам, когда ваш массив очень длинный (например, первый).

Еще один трюк - создание статической функции, которая выдает значение бита (как логическое значение) напозиция бита в массиве.В этом случае позиция (являющаяся константой) обязательно находится в диапазоне int.

public static bool GetBit(byte[] buffer, int pos)
{
  return (buffer[pos >> 3] & (1 << (pos & 7)) != 0);
}

Надеюсь, это поможет.

0 голосов
/ 12 августа 2011
...