Best way to represent Bit Arrays in C#? - c#

I am currently building a DHCPMessage class in c#.
RFC is available here : http://www.faqs.org/rfcs/rfc2131.html
Pseudo
public object DHCPMessage
{
bool[8] op;
bool[8] htype;
bool[8] hlen;
bool[8] hops;
bool[32] xid;
bool[16] secs;
bool[16] flags;
bool[32] ciaddr;
bool[32] yiaddr;
bool[32] siaddr;
bool[32] giaddr;
bool[128] chaddr;
bool[512] sname;
bool[1024] file;
bool[] options;
}
If we imagine that each field is a fixed length bit array, what is :
The most versitile
Best practice
way of representing this as a class???
OR.. how would you write this? :)

For starters, you might try the BitArray class. No need to reinvent the wheel here.
If you're worried about it taking up too much space/memory, don't be. Just initialize it to the right size:
BitArray op = new BitArray(8);
(The above will hold 8 bits and should take up 1 byte)

You are on the wrong track with this, it isn't a bit vector. The message is defined in "octets", better known as "bytes". An equivalent C# declaration that you can use with Marshal.PtrToStructure is:
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
struct DHCPMessage {
public byte op;
public byte htype;
public byte hlen;
public byte hops;
public uint xid;
public ushort secs;
public ushort flags;
public uint ciaddr;
public uint yiaddr;
public uint siaddr;
public uint giaddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]
public byte[] chaddr;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
public string sname;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string file;
}
You'll need to handle the variable length options field separately.

Are you sure you want to be using bit arrays for some of these? For example, you can use byte for 8 bits, int for 32 bits, and byte arrays for pieces that map to null terminated strings like 'sname' for example. Then you can use simple bitwise operators (&, |) to check/manipulate the bits.
Here are some posts I did on converting TCP header to a structure, which also covers endianness etc.
http://taylorza.blogspot.com/2010/04/archive-structure-from-binary-data.html
http://taylorza.blogspot.com/2010/04/archive-binary-data-from-structure.html
These are quite old, I migrated them from my old blog just so they do not get lost.

Related

Marshal.Sizeof() returning unexpected value

I'm debugging code in C# written by a 3rd party. The project is an old C++ project that was rewritten in C# by a contractor, and I have no access to the contractor. I authored the original C++ version.
The issue is when the C# code gets the size of a structure that represents data received over a UDP connection.
The struct is defined as:
[StructLayout(LayoutKind.Sequential,Pack=1)]
internal class PROXY_HDR {
public ushort pad;
public ushort label;
public char flags;
public ushort length;
public char[] ip = new char[4];
public ushort port;
}
The size of this struct is retrieved as:
int size = Marshal.Sizeof(typeof(PROXY_HDR));
and the value returned is 17 instead of the expected 13. With a 4-byte difference, I suspect the ip member, but only because it's expressed differently than the other members (with 'new'), but I have no other basis to decide.
I don't typically use this type of marshaling in my C# code that parses received packets without a problem, so I don't know how to modify this struct definition to make it 'line up' with the original version size-wise.
I could replace the Marshal line with
int size = 13;
but that's cheating, right?
Can I modify this layout somehow to get the size to come out right?
Add this to the structure:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal class PROXY_HDR
{
public ushort pad;
public ushort label;
public byte flags;
public ushort length;
[MarshalAs(UnmanagedType.ByValArray,
SizeConst = 4, ArraySubType = UnmanagedType.U1)]
public byte[] ip;
public ushort port;
}
This will tell the compiler to treat it as a typical C-style array, not a pointer. This should be byte, as an IP address is an unsigned char array. char typically isn't used in these types of headers, it's usually byte (i.e: unsigned char)

safe fixed size array in struct c#

I have a C struct in an embedded MCU with about 1000 elements, and it contains lots of fixed size arrays and other structs inside, Now I want to bring the data to PC Using C#
Here is a simple preview of my struct elements in C
struct _registers
{
char name[32];
float calibrate[4][16];
float DMTI;
float DMTII;
float DMTIII;
float DMTIE;
float DMTIIE;
....
};
Now I want to convert the Struct into C# using the GCHandle class,
something like this
//The C struct is in this byte array named buffer
byte[] buffer = new byte[4096];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
_registers stuff = (protection_registers)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(_registers));
handle.Free();
the problem is that the Visual studio complains about the "Pointers and fixed size buffers may only be used in an unsafe context"
is there a way to use it normally without unsafe code? I have found Doing something like this
[StructLayout(LayoutKind.Explicit, Size = 56, Pack = 1)]
public struct NewStuff
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
[FieldOffset(0)]
public string name;
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(32)]
public float calibrate[4][16];
}
but as the Code on the MCU is evolving in the coming years and we will add lots of functionality and parameter to the Struct, and since the struct has already 1000 elements, how we can do it better and more clever way? because keep tracking of all the offsets is very hard and error prone!
Try doing something like this instead (note: using class instead of struct which is more appropriate for C# - still marshals OK to a C++ struct):
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class NewStuff
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public StringBuilder name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4*16)]
public float[,] calibrate;
[MarshalAs(UnmanagedType.R4)]
public float DMTI;
[MarshalAs(UnmanagedType.R4)]
public float DMTII;
// Etc
}
You won't be able to remove the SizeConst since the marshalling needs to know this.
Also, when you intialise the class, you will need to set the array fields to the appropriate sized buffers, and initialise the StringBuilder with the correct buffer size.
Doing it this way means you can avoid using fixed buffers (and hence, you avoid the unsafe code).

PInvoke - Attempted to read or write protected memory. This is often an indication that other memory is corrupt

I've seen the attempted to read or write protected memory error before.
Typically the error shows up when I don't set up the c# struct correctly. I do have other calls working properly but this one is not co-operating.
I'm almost certain that it could be both my function call and the struct that is causing the problem.
C Syntax
int CardTransaction(pTRequest req, char *ProductCodes)
Request structure (I condensed it b/c there were repetitive data types)
typedef struct _cardRequest
{
unsigned short RedemptionNum
long TotalAmount;
unsigned char filler1[257];
char CardNumber[80];
unsigned char cardType;
} TRequest, *pTRequest;
C# function call
[DllImport("card.dll"), CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern int CardTransaction(ref CardRequest cardRequest, [MarshalAs(UnManagedType.LPStr)] StringBuilder productCodes);
ProductCodes is null so I just instantiated a stringbuilder object with nothing in it and passed it through. This is one place I'm thinking could be a problem.
C# structure
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct CardRequest
{
public uint16 RedemptionNum
public int TotalAmount;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
public string filler1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string CardNumber;
public byte cardType;
}
The obvious problem is that the C code uses an aligned struct, but for some reason you have elected to pack the C# struct. Remove the Pack = 1 from the C# code to make the two structures match.
Beyond that the filler array looks more like a byte array than a string. I'd declare it like this:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 257)]
public byte[] filler1;
If you want to pass null to the productCodes parameter, then I expect you can do just that. I cannot recall every doing that myself, but generally when you pass null to a p/invoke, then the marshaller will pass NULL to the native code.

StructLayout to convert byte array to short

Sorry about the horrible title but I honestly have know idea what I want nor what is wrong...
Basically I have a struct (well I have 250+ structs but they all follow the same idea) that looks like this:
[StructLayout(LayoutKind.Explicit)]
public struct GenericPacket
{
[FieldOffset(0)]
public byte[] data;
[FieldOffset(0)]
public short packetid;
}
The issue is that a byte array is a reference type and a short is a value type and it won't allow the fieldoffset to be set to the same memory location...
I would really hate to have to remove all the structs I've written just to do it a different way. So here is my question, how can I use this in a way that works. Basically what I'm going to do is this:
socket.Receive(buff, 0, 0, SocketFlags.None);
GenericPacket packet = new GenericPacket();
packet.data = buff;
Console.WriteLine(packet.packetid);
It refuses to even compile as it doesn't want to generate the struct /:
Before anyone suggests other methods, the reason I am doing this is it needs ultra high speeds... I could use a ByteReader and other methods (eg. BitConverter) but it needs to be a tad faster than that...
I started with Bitwise shifts but I needed a more 'dynamic' way to do it because after I have a packet ID I then read it with another struct, for example:
[StructLayout(LayoutKind.Explicit)]
public struct _03k
{
[FieldOffset(0)]
byte[] data;
[FieldOffset(0)]
short packetid;
[FieldOffset(2)]
short #null;
[FieldOffset(4)]
int major;
[FieldOffset(8)]
int minor;
[FieldOffset(12)]
int build;
}
Instead of having to have a lot of inline "Bitwise shits" I simply want an easy AND very fast way of doing this... Seems I got the fast just not the easy /:
PLEASE HELP! Unsafe code is ok, but prefer a managed version too.
FAIL :(: Just remembered you can convert Value types to Reference types by boxing them (casting to type object). This does however remove the REAL return type and says it just is an object, is there anyway with XML Documentation that you can lie about the return type?
DOESN'T WORK SADLY D:
UPDATE: OK, now I have:
public struct GenericPacket
{
public short packetid;
public static GenericPacket ReadUsingPointer(byte[] data)
{
unsafe
{
fixed (byte* packet = &data[0])
{
return *(GenericPacket*)packet;
}
}
}
}
But its a bit annoying having to call a method everytime to convert it :( Anyone got any more suggestions?
Thanks, JD
You just want to convert the first two bytes of the array to a short, how does that pose any performance problem?
packetid = ((short)data[0] << 8) | data[1];
Or the other way around if you want the other endianess.
EDIT:
So you want to parse multiple fields. Don't reinvent the wheel, then. Use Google's Protocol Buffers, it's very fast and efficient, and I doubt you'd encounter performance issues with it. Here's a .NET port.
I've just found you can use fixed araays in structs:
[StructLayout(LayoutKind.Explicit)]
unsafe struct Union
{
[FieldOffset(0)]
public short x;
[FieldOffset(0)]
public fixed byte y[2];
}
The initialization:
var u = new Union();
byte[] y = new byte[2]; //your original array here
int len = y.Length;
unsafe
{
fixed (byte* s= y)
{
byte* source = s;
byte* dest = u.y;
for (int i = 0; i < len; i++)
{
*dest++ = *source++;
}
}
}
In this particular example you could do this:
[StructLayout(LayoutKind.Explicit)]
struct byte_array
{
[FieldOffset(0)]
public byte byte1;
[FieldOffset(1)]
public byte byte2;
[FieldOffset(0)]
public short packetid;
}
But in general, Buffer.BlockCopy is probably a better solution.
What I finally settled on was a struct with an implicit conversion operator that called the ReadByPointer method.
public struct GenericPacket
{
public short packetid;
public static GenericPacket ReadUsingPointer(byte[] data)
{
unsafe
{
fixed (byte* packet = &data[0])
{
return *(GenericPacket*)packet;
}
}
}
static public implicit operator GenericPacket(byte[] value)
{
return GenericPacket.ReadUsingPointer(value);
}
}
This allows you to do the following:
GenericPacket packet = bufferFromReceive;
Thanks -jD

How can C++/CLI make this situation easier?

I have a little piece of a library that I would like to write a .NET wrapper for. At the moment, I'm using P/Invoke, but since I don't have the library's source code or a whole lot of C knowledge, I'm having a difficult time with marshaling. It works so far (sort of), but it feels like a hack.
C Signatures
typedef struct
{
unsigned short sAddress[MAX_ADDRESS_CHAR_LENGTH + 1];
unsigned short sCallback[MAX_CALLBACK_CHAR_LENGTH + 1];
unsigned short sMessage[(MAX_MESSAGE_CHAR_LENGTH + 1) ];
unsigned short sSmscAddress[MAX_ADDRESS_CHAR_LENGTH+1];
unsigned short sSubject[MAX_SUBJECT_CHAR_LENGTH + 1];
unsigned char msgLength;
unsigned char pduType;
unsigned short msgRef;
unsigned char msgSequence;
unsigned char msgTotal;
EMsgPriority nPriority;
struct tm tTime;
EncodingType encoding;
unsigned char bReceipt;
unsigned long dwDataMask;
struct tm tValidity;
unsigned char nValidityType;
unsigned char bRelativeValidityFlag;
unsigned char isDeliveryAck;
} SMS_MSG_DATA;
unsigned short SmsEncodeMessage( SMS_MSG_DATA* sms_msg, unsigned char* msg_buf,
unsigned short* msg_buf_len );
C# P/Invoke
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SMS_MSG_DATA {
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst=SmsEncoding.MAX_ADDRESS_CHAR_LENGTH+1)]
public string sAddress;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst=SmsEncoding.MAX_CALLBACK_CHAR_LENGTH+1)]
public string sCallback;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst=SmsEncoding.MAX_MESSAGE_CHAR_LENGTH+1)]
public string sMessage;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst=SmsEncoding.MAX_ADDRESS_CHAR_LENGTH+1)]
public string sSmscAddress;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst=SmsEncoding.MAX_SUBJECT_CHAR_LENGTH+1)]
public string sSubject;
public byte msgLength;
public byte pduType;
public ushort msgRef;
public byte msgSequence;
public byte msgTotal;
public EMsgPriority nPriority;
public tm tTime;
public EncodingType encoding;
public byte bReceipt;
public long dwDataMask;
public tm tValidity;
public byte nValidityType;
public byte bRelativeValidityFlag;
public byte isDeliveryAck;
}
[DllImport(Constants.LIB_SMSENCODE)]
public static extern ErrorCode SmsEncodeMessage(ref SMS_MSG_DATA sms_msg,
byte[] msg_buf, ref short msg_buf_len);
Essentially, what this does is takes the SMS_MSG_DATA struct and outputs it to a binary format in the msg_buf byte array. The initial value of msg_buf_len is the size of the byte array, but when the encoding completes, it is set to the number of bytes actually filled.
How can a C++/CLI wrapper make this process any easier and cleaner?
This is perfectly reasonable P/Invoke code, though you should make sure that you are not passing Unicode around (check your struct defn.), because all your native declarations seem to take ANSI strings.
C++/CLI doesn't really help you too much here - the place where it makes your life easier is when you want to write some blocks of native code, and make the interface to the C# part simpler. The only thing you could do here, is if on the C# side you really only cared about 1-2 params, you could have the C++/CLI DLL fill out the rest for you and not worry about as much ugly code on the C# side
C++/CLI can make this easier because you don't have to write a PInvoke definition. Instead you can just use the original native SMS_MSG_DATA structure directly. You are free to write a better looking wrapper structure which is internally converted to SMS_MSG_DATA. This wrapper structure need not have any ugly PInvoke declaration and can be much more in lines with managed guidelines.

Categories

Resources