C++ - C#, статическое приведение в перечисление
Я пытаюсь преобразовать немного кода VC 6.0 C++ в C#. В частности, я анализирую двоичный файл dat и столкнулся с проблемой преобразования этого бита кода:
ar.GetFile()->Read(buf,sizeof(int));
memmove(&x,buf,4);
pEBMA->before_after = static_cast<enum EBMA_Reserve>(x);
pEBMA->method = static_cast<enum EBMA_Method>(x >> 4);
Вот несколько связанных кодов.
struct EBMA_Data *pEBMA = &EBMA_data;
typedef CArray<struct EBMA_Data,struct EBMA_Data&> EBMA_data;
enum EBMA_Reserve
{EBMA_DONT_RESERVE,
EBMA_BEFORE,
EBMA_AFTER
};
enum EBMA_Method
{EBMA_CENTER,
EBMA_ALL_MATERIAL,
EBMA_FRACTION,
EBMA_RESERVE
};
struct EBMA_Data
{double reserved;
double fraction;
enum EBMA_Method method : 4;
enum EBMA_Reserve before_after : 4;
};
Я прочитал этот поток здесь приведение int к Enum в C#, но мой код не дает мне тех же результатов, что и устаревшая программа.
Вот некоторые из моих кодов в C#:
reserved = reader.ReadDouble();
fraction = reader.ReadDouble();
beforeAfter = (EBMAReserve)Enum.ToObject(typeof(EBMAReserve), x);
method = (EBMAMethod)Enum.ToObject(typeof(EBMAMethod), (x >> 4));
У меня действительно есть проблема эндианнесса, поэтому я обращаю эндианнесс, как так.
public override double ReadDouble()
{
byte[] b = this.ConvertByteArrayToBigEndian(base.ReadBytes(8));
double d = BitConverter.ToDouble(b, 0);
return d;
}
private byte[] ConvertByteArrayToBigEndian(byte[] b)
{
if (BitConverter.IsLittleEndian)
{
Array.Reverse(b);
}
return b;
}
И тогда я подумал, что, возможно, проблема эндианства все еще сбивает меня с толку, поэтому вот еще одна попытка:
byte[] test = reader.ReadBytes(8);
Array.Reverse(test);
int test1 = BitConverter.ToInt32(buffer, 0);
int test2 = BitConverter.ToInt32(buffer, 4);
beforeAfter = (EBMAReserve)test1;
method = (EBMAMethod)test2;
Надеюсь, я достаточно подробно рассказал о том, что пытаюсь сделать.
Редактировать:
Вот как я решил свою проблему, по-видимому, нужные мне значения были сохранены в первом байте 4-байтового сегмента в двоичном файле. Это в цикле.
byte[] temp = reader.ReadBytes(4);
byte b = temp[0];
res = (EBMAReserve)(b & 0x0f);
meth = (EBMAMethod)(b >> 4);
1 ответ:
EDIT: на самом деле похоже, что размер структуры
EBMA_Data
составляет 17 байт.struct EBMA_DATA { double reserved; //(8 bytes) double fraction; //(8 bytes) enum EBMA_Method method : 4; //(this is packed to 4 bits, not bytes) enum EMBA_Reserve before_after : 4; //(this too, is packed to 4 bits) }
Таким образом, ваш код чтения должен выглядеть примерно так:
EBMA_Data data = new EBMA_Data; data.reserved = reader.ReadDouble(); data.fraction = reader.ReadDouble(); byte b = reader.ReadByte(); data.method = (EBMAMethod)(b >> 4); data.before_after = (EBMAReserve)(b & 0x0f);
Не уверен на 100%, но похоже, что код, который делает сдвиг
x >> 4
байт, может быть основной проблемой, которую упускают из виду. ЕслиEBMAReserve
- это нижние 4 бита x, аEBMAMethod
- верхние 4 бита, может быть, этот код будет работать?EBMAReserve res = (EBMAReserve)(x & 0x0f); EBMAMethod meth = (EBMAMethod)(x >> 4);
Я думаю, что это то, что означает
: 4
после перечислений в структуре, это упаковка двух перечислений в структуру в виде одного байта вместо 2 байтов.