Ralph Varjabedian
Coding is a systematic art

Casting a byte array into structures in C#

Tuesday, July 29, 2008 3:09 PM

Looking around the web, developers often need to cast (map) a byte array into some sort of a structure. In C++, it is as easy as casting the byte array pointer to your structure pointer, however in the managed world of .NET things are different and you can not do this anymore. Let us visit the different approaches developers use to solve this problem.

Some developers choose to write a helper class that makes use of BinaryReader to read values from the binary array depending on the structure they have and write them directly into members of the structure. This method is fast but needs a lot of maintenance since you need to code a class or a method for each structure you have and you need to update it if your structure changes. This solution uses fully managed code.

Other developers choose to use unsafe code and cast the byte array directly into the memory of the structure. The structure should be packed on 1 byte boundary and it should have a sequential layout. And you can not cast your byte array into a class using this method. This method is very fast however it uses unsafe code which is not encouraged because your CLR can not do proper memory checks on this structure anymore. Also since this is not a managed solution you can not port it to VB.NET, as far as I know you can only use unsafe blocks in C#.

Another solution involves getting the help of the Marshal class to cast your structure. However this solution involves copying data between managed and unmanaged heap which is slow and consumes resources, however this solution works on VB.NET and not just C#.

Some developers choose to use reflection code. This solution is similar to the first solution (BinaryReader) but instead of coding a method for each structure you want, reflection is used to automate things and make things "more dynamic". Using this method, instead of coding the actual read operations from the stream into your structure members at compile time, this is decided at runtime by using reflection to detect the members of your structure. This solution saves you a lot of donkey work, unfortunately reflection is slow, very slow compared to normal code. Depending on your application, you might not care much if your code is slow to cast the byte array into your corresponding structure, but if speed is essential, (for example in a network analysis tool) then you need a faster solution than this.

A quick Google search revealed a lot of articles on the subject. I have chosen this article that explains these methods with more details:

http://www.dotnetjunkies.ddj.com/Article/DF6E5BE5-BCB6-43BB-BEE4-1013A2E3D085.dcik

Today I am going to get the help of my friend Mr. Emit, the virtual developer who works for me for free. Using Emit namespace, I will be able to write a solution that is as fast as the first solution (manually coding the read operations of BinaryReader into the members of a structure) and as dynamic as the reflection solution, and the solution will be using fully manageable code and does not involve copying of memory between managed and unmanaged heaps. The solution mostly resembles the first solution but without any of the donkey work, it is fully dynamic.

My solution takes a structure at runtime and uses reflection to detect its members (fields or properties). After detecting the members, the Emit namespace is used to write IL code and create a new class at runtime that uses the BinaryReader approach to read data from the byte array into the structure's members. Unlike using simple reflection code (which has to use reflection every time you want to cast a byte array to any structure), I use reflection once to write a class at runtime that does the casting without reflection. Of course the new dynamically written class is cashed for subsequent castings of the same structure type.

You can find the sample application here.

How to use the code:

Using the code is very simple as it is shown in the sample application. Casting involves simple lines of code like this:

byte[] data = new byte[] { 0, 0, 0, 1, 0, 2, 3, 4, 5, 6, 7 };

SampleStructure stru = new SampleStructure();
stru = (SampleStructure)CDynamicCastHelper.CastIntoFields(stru, data, 
    CastOptions.ReverseDWord | CastOptions.ReverseWord);

SampleClass clas = new SampleClass();
CDynamicCastHelper.CastIntoFields(clas, data, 
    CastOptions.ReverseDWord | CastOptions.ReverseWord);

 

You have two methods to use in the class CDynamicCastHelper, CastIntoFields and CastIntoProperties. The first one casts the byte array into fields and the second one casts the byte array into properties. The methods can take either a structure or a class and they take CastOptions enum. CastOptions can reverse 16bit (WORD) and 32bit (DWORD) values for you while being read. If your structure or class has a byte array member that you want to cast data into it, then you must add a special attribute to your byte array member that specifies the size that the CDynamicCastHelper will fill into this byte array member.

If someone can volunteer to port this to VB.NET that would be great, please let me know.

Hope this helps. Let me know if you have any comments.


Feedback

# re: Casting a byte array into structures in C#

The link to the sample application is broken. 11/4/2008 4:33 PM | None

# re: Casting a byte array into structures in C#

Nevermind, working now. 11/4/2008 4:35 PM | None

# re: Casting a byte array into structures in C#

This is a great article. Thank you.

You said: "If your structure or class has a byte array member that you want to cast data into it, then you must add a special attribute to your byte array member that specifies the size that the CDynamicCastHelper will fill into this byte array member."

Could you give me an example code? I am a new C#er.

Thank you in advance for your time. 12/3/2008 11:29 PM | cren

# re: Casting a byte array into structures in C#

Hi cren.

You need to add the attribute
DynamicCastHelperSizeAttribute
on the property that contains the byte array.

The attribute is very simple, it just takes the size of the array.

Something like this (10 byte array)

class TestStructure
{
[DynamicCastHelperSizeAttribute(10)]
public byte[] Data
{get;set;}
}

Regards. 12/4/2008 11:02 AM | Ralph Varjabedian

# re: Casting a byte array into structures in C#

Thank you very much.

12/4/2008 10:31 PM | cren

# re: Casting a byte array into structures in C#

Can you use the DynamicCastHelperSizeAttribute on arrays of another structure with a structure?

For example:

[DynamicCastHelperSizeAttribute(7)]
AuxInput[] m_inputs;

Where AuxInput is defined as:
private class AuxInput
{
Byte m_input;
Byte m_CD;
Byte m_CO;
Byte m_KW;
};

Thanks for your help.
David
1/9/2009 8:45 AM | David Griggs

# re: Casting a byte array into structures in C#

Well no, not currently at least, but the code could be modified to allow filling of nested structures, it would require some recursion. I will try to update the code for the future. Thanks. 1/12/2009 11:58 AM | Ralph Varjabedian

# re: Casting a byte array into structures in C#

I like using your helper class and added some other types UInt16, UInt32 etc.
I am having trouble parsing arrays from the byte array and I am using [DynamicCastHelperSizeAttribute(n)]
Also it is only possible for the structure or class to have only one byte[] type?

Can I read in
public struct s
{
Int16 a; ...
[DynamicCastHelperSizeAttribute(10)]
byte[] b;
Int32 c;
[DynamicCastHelperSizeAttribute(10)]
byte[] d;
}
3/31/2009 11:30 PM | Leo

# re: Casting a byte array into structures in C#

Hello Leo,

What is the problem exactly, is it crashing, is it filling the wrong data size or not filling at all, if you have a working sample project with your problem let me know, so I can send you an email address to email me on.

As for 1 byte type, it should be simple enough, just add it like the other simple types you have added, it should work.

Regards. 4/1/2009 11:50 AM | Ralph Varjabedian

# re: Casting a byte array into structures in C#

You might be interested to look at this product:
www.versatile-serializing.net
5/2/2009 12:04 AM | Karsten Strobel

# re: Casting a byte array into structures in C#

Karsten, this is interesting. How are you doing the converstion at runtime? Are you using serialization purely? or are you using something like I described here?

Thanks. 5/19/2009 3:10 PM | Ralph Varjabedian

# re: Casting a byte array into structures in C#

Ralph, yes, this library does conversions at runtime. It uses a system of special parameterizable attributes that can be tagged to instance members (fields) to describe their mapping to binary data. Though this approach uses reflection, there are some cachings and other means to keep performance acceptable. What the library can do goes far beyond simple mapping of fields to bytes. One example that is provided with the demo is an implementation for the snmp protocol based on versatile serialization for example... 5/19/2009 9:48 PM | Karsten Strobel

# re: Casting a byte array into structures in C#

The article would have helped me in understanding structs and their usage.Thanks for the update of your journey. 12/14/2009 3:04 PM | http://www.onlinecasinoscd.com/

# re: Casting a byte array into structures in C#

Karsten, this is interesting. How are you doing the converstion at runtime? Are you using serialization purely 12/22/2009 8:26 AM | Shared Web Hosting

# re: Casting a byte array into structures in C#

I am not sure how Karsten is doing it, but as far I can tell there is no faster method than the method I have presented, granted that you are using managed code. 12/22/2009 1:06 PM | Ralph Varjabedian

# re: Casting a byte array into structures in C#

I tested the demo app and I was wondering if anyone sees a problem with the following instead of this class for simple situations:

ORIGINAL:
SampleStructure stru = new SampleStructure();
stru = (SampleStructure)CDynamicCastHelper.CastIntoFields(stru, data, CastOptions.ReverseDWord | CastOptions.ReverseWord);

UPDATED (and much faster):
GCHandle dd = GCHandle.Alloc(data, GCHandleType.Pinned);
SampleStructure ss = (SampleStructure)Marshal.PtrToStructure(dd.AddrOfPinnedObject(), Type.GetType("DynamicCastHelper.Form1+SampleStructure"));

2/10/2010 4:25 PM | MAC

# re: Casting a byte array into structures in C#

im using Visual Studio 2010 Beta 2

I tried to import the class into my code. I get this.

An unhandled exception of type 'System.TypeAccessException' occurred in DynamicCaster.DynamicModule.dll

but if i compile the original project, it works fine. 2/24/2010 12:03 AM | EnriqueH

# re: Casting a byte array into structures in C#

Working with your Class, It works for the most part, thanks... however byte[] and string are classes and take a different path in your code and therefore really don't work.

The code segment is:
IsClass is returning true for byte[] and string but doesn't copy properly.
// Commented out.. doesn't support string or byte[] classes... needs fixing
//if (objProperty.PropertyType.IsClass)
//{

I'm using class structure and calling
CDynamicCastHelper.CastIntoProperties(IRclass, data, CastOptions.ReverseDWord | CastOptions.ReverseWord);

which it I don't execute the IsClass check works fine. I will try and debug the section of code, if you want to look at what I did, I can email you the project. 3/12/2010 8:46 PM | blair

Post a comment





 

Please add 8 and 1 and type the answer here: