C++ to C#, static_cast into enum
I'm trying to convert a bit of VC 6.0 C++ code to C#. Specifically, I'm parsing through a binary dat file and I've run into a problem converting this bit of code:
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);
Here is some related code.
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;
};
I've read this thread here Cast int to Enum in C#, but my code isn't giving me the same results as the legacy program.
Here is some of my code in C#:
reserved = reader.ReadDouble();
fraction = reader.ReadDouble();
beforeAfter = (EBMAReserve)Enum.ToObject(typeof(EBMAReserve), x);
method = (EBMAMethod)Enum.ToObject(typeof(EBMAMethod), (x >> 4));
I do ha开发者_Go百科ve an endianness problem so I am reversing the endianness like so.
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;
}
So then I thought that maybe the endianness issue was still throwing me off so here is another attempt:
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;
I hope I've given enough details about what I'm trying to do.
EDIT:
This is how I solved my issue, apparently the values I needed were stored in the first byte of a 4 byte segment in the binary file. This is in a loop.
byte[] temp = reader.ReadBytes(4);
byte b = temp[0];
res = (EBMAReserve)(b & 0x0f);
meth = (EBMAMethod)(b >> 4);
EDIT: It actually looks like the structure size of EBMA_Data
is 17 bytes.
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)
}
so your read code should look something more like this:
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);
Not 100% sure, but it looks like the code that does the shift x >> 4
bytes may be the underlying issue that's being overlooked. If the EBMAReserve
is the lower 4 bits of x and EBMAMethod
is the top 4 bits, maybe this code would work?
EBMAReserve res = (EBMAReserve)(x & 0x0f);
EBMAMethod meth = (EBMAMethod)(x >> 4);
I think that is what the : 4
means after the enumerations in the struct, it's packing the two enums into the structure as a single byte instead of 2 bytes.
精彩评论