cast from "array of byte" to "array of struct"

P

Pablo Gutierrez

I have a C# method that reads Binary data (BLOB type) from a database
and returns the data an array of bytes
(i.e byte[] outbyte = new byte[bufferSize];).

The BLOB column is saved into the database by a C program (UNIX) as an
array of "struct point" where

struct point //C structure
{
int Time; //32 bits
float Value; //32 bits
};


How can I cast the byte array read in the C# method to an array of
Sample where

public struct Sample //C# structure
{
System.Int32 Time; //32 bits
System.Single Value; //32 bits
}
?

In C/C++ this is extremely simple using pointers, but which is the
best way of doing this in C#?
 
R

Rob Teixeira [MVP]

C# - and most .NET languages for that matter - are very strongly typed
languages. The data type integrity and strict interpretation not only cut
down on bugs, but allow for better code security. However, that means you
cannot cast arbitrary buffers to or from other datatypes.
You will have to create a separate variable of the struct type, then convert
and copy the bytes to the struct's members.
You can use System.BitConverter to help you do the byte-to-other-type
conversion. However, since your data was created by a Unix program, there is
a real chance that you will have issues concerning big-endian vs. little
endian integer types - in other words, the high-low byte orders for your int
may be reversed. If that's the case, you cannot use BitConverter, and must
do manual bit shifting on the bytes to assemble the int part of your
structure.
As an alternative, you can pin the byte array and use the
System.Runtime.Interop.Marshal.UnsafeAddrOfPinnedArrayElement in conjunction
with System.Interop.Marshal.PtrToStruct. But, realize that in either case,
you creating a copy of the data from the buffer, and not merely casting the
buffer itself. That isn't possible unless you drop to Unsafe code blocks,
which I don't usually recommend. And more importantly, realize that this
method is still prone to the int endian problem. That being the case, your
best bet may be to just bite the bullet and do the manual bit shifting.

-Rob Teixeira [MVP]
 
M

mikeb

Rob said:
C# - and most .NET languages for that matter - are very strongly typed
languages. The data type integrity and strict interpretation not only cut
down on bugs, but allow for better code security. However, that means you
cannot cast arbitrary buffers to or from other datatypes.
You will have to create a separate variable of the struct type, then convert
and copy the bytes to the struct's members.
You can use System.BitConverter to help you do the byte-to-other-type
conversion. However, since your data was created by a Unix program, there is
a real chance that you will have issues concerning big-endian vs. little
endian integer types - in other words, the high-low byte orders for your int
may be reversed. If that's the case, you cannot use BitConverter, and must
do manual bit shifting on the bytes to assemble the int part of your
structure.
As an alternative, you can pin the byte array and use the
System.Runtime.Interop.Marshal.UnsafeAddrOfPinnedArrayElement in conjunction
with System.Interop.Marshal.PtrToStruct. But, realize that in either case,
you creating a copy of the data from the buffer, and not merely casting the
buffer itself. That isn't possible unless you drop to Unsafe code blocks,
which I don't usually recommend. And more importantly, realize that this
method is still prone to the int endian problem. That being the case, your
best bet may be to just bite the bullet and do the manual bit shifting.

-Rob Teixeira [MVP]

Note that IPAddress.NetworkToHostOrder() will convert big-endian ints to
the native byte order.
I have a C# method that reads Binary data (BLOB type) from a database
and returns the data an array of bytes
(i.e byte[] outbyte = new byte[bufferSize];).

The BLOB column is saved into the database by a C program (UNIX) as an
array of "struct point" where

struct point //C structure
{
int Time; //32 bits
float Value; //32 bits
};


How can I cast the byte array read in the C# method to an array of
Sample where

public struct Sample //C# structure
{
System.Int32 Time; //32 bits
System.Single Value; //32 bits
}
?

In C/C++ this is extremely simple using pointers, but which is the
best way of doing this in C#?
 
S

Steve Waggoner

I have a C# method that reads Binary data (BLOB type) from a database
and returns the data an array of bytes
(i.e byte[] outbyte = new byte[bufferSize];).

How can I cast the byte array read in the C# method to an array of
Sample where

public struct Sample //C# structure
{
System.Int32 Time; //32 bits
System.Single Value; //32 bits
}


Something like this will convert a bytes a C# structure...


byte[] sourceData;
MyStruct destStruct;
int arrayIndex = 0;

GCHandle handle = GCHandle.Alloc(sourceData, GCHandleType.Pinned);
try
{
IntPtr buffer = handle.AddrOfPinnedObject();
buffer = (IntPtr)(buffer.ToInt32() +
(arrayIndex*Marshal.SizeOf(typeof(MyStruct))));
destStruct = (MyStruct)Marshal.PtrToStructure(buffer, typeof(MyStruct));
}
finally
{
handle.Free();
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top