byte[] to struct

  • Thread starter Thread starter Ben Terry
  • Start date Start date
B

Ben Terry

What's the most efficient way to transfer data from a byte[] to a struct?
The struct is rather complex--contains other structs as well as byte[]
members. I've tried to use Marshal.Copy and an IntPtr to my struct address
but I get the following error, perhaps due to the byte[] members of my
struct:
Cannot take the address or size of a variable of a managed type.

Ben
 
You can just mark the struct as serializable and then use some code like the
following:

BinaryFormatter formatter = new BinaryFormatter();
YourStruct str = new YourStruct();
MemoryStream ms = new MemoryStream();
formatter.Serialize(ms, str);
byte[] buffer = ms.ToArray();
 
Sorry you wanted the reverse... in which case you can create a MemoryStream
on the byte[] and use the Deserialize method of the BinaryFormatter to
create the struct from the buffer.
 
Thanks for the help, John. I've tried what you suggested:

MemoryStream ms = new MemoryStream(m_ReceivedBytes);
BinaryFormatter bf = new BinaryFormatter();
m_CompleteIllumStateMsg = (MIX_CompleteIllumStateMsg)bf.Deserialize(ms);

Where m_ReceivedBytes is a byte[] and m_CompleteIllumStateMsg is my
structure. I get the following exception when I try to Deserialize:
"BinaryFormatter Version incompatibility. Expected Version 1.0. Received
Version 43.0." } System.Exception
Any thoughts on how to resolve this?

Ben

John Wood said:
Sorry you wanted the reverse... in which case you can create a MemoryStream
on the byte[] and use the Deserialize method of the BinaryFormatter to
create the struct from the buffer.

--
John Wood
EMail: first name, dot, second name at priorganize.com


Ben Terry said:
What's the most efficient way to transfer data from a byte[] to a struct?
The struct is rather complex--contains other structs as well as byte[]
members. I've tried to use Marshal.Copy and an IntPtr to my struct address
but I get the following error, perhaps due to the byte[] members of my
struct:
Cannot take the address or size of a variable of a managed type.

Ben
 
What John suggested only works if the byte[] contains serialized
data. What you actually want to look at is unsafe code. You can
use MarshalPtrToStructure and MarshalStructureToPtr as long as
your struct has layout information.

Note the above two methods aren't necessarily unsafe because the
CLR implements them for you, but they do require high privs, and
if I'm not mistaken they do require unmanaged code permissions.

--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

Ben Terry said:
Thanks for the help, John. I've tried what you suggested:

MemoryStream ms = new MemoryStream(m_ReceivedBytes);
BinaryFormatter bf = new BinaryFormatter();
m_CompleteIllumStateMsg = (MIX_CompleteIllumStateMsg)bf.Deserialize(ms);

Where m_ReceivedBytes is a byte[] and m_CompleteIllumStateMsg is my
structure. I get the following exception when I try to Deserialize:
"BinaryFormatter Version incompatibility. Expected Version 1.0. Received
Version 43.0." } System.Exception
Any thoughts on how to resolve this?

Ben

John Wood said:
Sorry you wanted the reverse... in which case you can create a MemoryStream
on the byte[] and use the Deserialize method of the BinaryFormatter to
create the struct from the buffer.

--
John Wood
EMail: first name, dot, second name at priorganize.com


Ben Terry said:
What's the most efficient way to transfer data from a byte[] to a struct?
The struct is rather complex--contains other structs as well as byte[]
members. I've tried to use Marshal.Copy and an IntPtr to my struct address
but I get the following error, perhaps due to the byte[] members of my
struct:
Cannot take the address or size of a variable of a managed type.

Ben
 
You have to ensure that the buffer you are using to create the MemoryStream
(the m_ReceivedBytes) was created using the Serialize method I mentioned
above.

If it is, could you provide some more code so I can try and reproduce it?

--
John Wood
EMail: first name, dot, second name at priorganize.com


Ben Terry said:
Thanks for the help, John. I've tried what you suggested:

MemoryStream ms = new MemoryStream(m_ReceivedBytes);
BinaryFormatter bf = new BinaryFormatter();
m_CompleteIllumStateMsg = (MIX_CompleteIllumStateMsg)bf.Deserialize(ms);

Where m_ReceivedBytes is a byte[] and m_CompleteIllumStateMsg is my
structure. I get the following exception when I try to Deserialize:
"BinaryFormatter Version incompatibility. Expected Version 1.0. Received
Version 43.0." } System.Exception
Any thoughts on how to resolve this?

Ben

John Wood said:
Sorry you wanted the reverse... in which case you can create a MemoryStream
on the byte[] and use the Deserialize method of the BinaryFormatter to
create the struct from the buffer.

--
John Wood
EMail: first name, dot, second name at priorganize.com


Ben Terry said:
What's the most efficient way to transfer data from a byte[] to a struct?
The struct is rather complex--contains other structs as well as byte[]
members. I've tried to use Marshal.Copy and an IntPtr to my struct address
but I get the following error, perhaps due to the byte[] members of my
struct:
Cannot take the address or size of a variable of a managed type.

Ben
 
I'm still not sure this is the right way to do it. Here's some more
information on the structs I am trying to build from the byte[].

The structure contains nested structures. The nested structures are
interesting because they are defined in a COM type library. I am using them
in my C# project by means of the tlbimp.exe that converts a COM type library
into a common language runtime assembly. I am referencing this assembly in
my C# project. The byte arrays in the nested structures are defined, for
example, as:

BYTE strBarcode[32]; // This is in the idl file that is compiled to COM
type library.

When I inspect these members in the object viewer after importing the
library into a runtime assembly they show up as, for example:

public byte[] strBarcode

I convert the structures to byte arrays in a C++ server program running on a
remote machine, and my C# client app reads them in and HOPEFULLY someday
will be able to fill up a struct identical to the one it originated from.

The CLR should know how big strBarcode is, right? If it does, I can't
understand why I can't simply do something like:

unsafe
{
MyStruct* p = &MyStruct;
Marshal.Copy(byteArray, (IntPtr)p, ....)
}

When I try code like this the compiler complains that I am trying to use the
address of a managed struct. If I remove those byte[] members from the
struct, the code compiles fine.

So my question remains, how can I simply load up my structure from a byte
stream? This seems like it should be so easy!

Ben

Justin Rogers said:
What John suggested only works if the byte[] contains serialized
data. What you actually want to look at is unsafe code. You can
use MarshalPtrToStructure and MarshalStructureToPtr as long as
your struct has layout information.

Note the above two methods aren't necessarily unsafe because the
CLR implements them for you, but they do require high privs, and
if I'm not mistaken they do require unmanaged code permissions.

--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

Ben Terry said:
Thanks for the help, John. I've tried what you suggested:

MemoryStream ms = new MemoryStream(m_ReceivedBytes);
BinaryFormatter bf = new BinaryFormatter();
m_CompleteIllumStateMsg = (MIX_CompleteIllumStateMsg)bf.Deserialize(ms);

Where m_ReceivedBytes is a byte[] and m_CompleteIllumStateMsg is my
structure. I get the following exception when I try to Deserialize:
"BinaryFormatter Version incompatibility. Expected Version 1.0. Received
Version 43.0." } System.Exception
Any thoughts on how to resolve this?

Ben

John Wood said:
Sorry you wanted the reverse... in which case you can create a MemoryStream
on the byte[] and use the Deserialize method of the BinaryFormatter to
create the struct from the buffer.

--
John Wood
EMail: first name, dot, second name at priorganize.com


What's the most efficient way to transfer data from a byte[] to a struct?
The struct is rather complex--contains other structs as well as byte[]
members. I've tried to use Marshal.Copy and an IntPtr to my struct
address
but I get the following error, perhaps due to the byte[] members of my
struct:
Cannot take the address or size of a variable of a managed type.

Ben
 
You might want to put the code in a 'fixed' block.
eg.
fixed (MyStruct* p = &MyStruct)
{
Marshal.Copy(byteArray, (IntPtr)p, ....)
}

--
John Wood
EMail: first name, dot, second name at priorganize.com


Ben Terry said:
I'm still not sure this is the right way to do it. Here's some more
information on the structs I am trying to build from the byte[].

The structure contains nested structures. The nested structures are
interesting because they are defined in a COM type library. I am using them
in my C# project by means of the tlbimp.exe that converts a COM type library
into a common language runtime assembly. I am referencing this assembly in
my C# project. The byte arrays in the nested structures are defined, for
example, as:

BYTE strBarcode[32]; // This is in the idl file that is compiled to COM
type library.

When I inspect these members in the object viewer after importing the
library into a runtime assembly they show up as, for example:

public byte[] strBarcode

I convert the structures to byte arrays in a C++ server program running on a
remote machine, and my C# client app reads them in and HOPEFULLY someday
will be able to fill up a struct identical to the one it originated from.

The CLR should know how big strBarcode is, right? If it does, I can't
understand why I can't simply do something like:

unsafe
{
MyStruct* p = &MyStruct;
Marshal.Copy(byteArray, (IntPtr)p, ....)
}

When I try code like this the compiler complains that I am trying to use the
address of a managed struct. If I remove those byte[] members from the
struct, the code compiles fine.

So my question remains, how can I simply load up my structure from a byte
stream? This seems like it should be so easy!

Ben

Justin Rogers said:
What John suggested only works if the byte[] contains serialized
data. What you actually want to look at is unsafe code. You can
use MarshalPtrToStructure and MarshalStructureToPtr as long as
your struct has layout information.

Note the above two methods aren't necessarily unsafe because the
CLR implements them for you, but they do require high privs, and
if I'm not mistaken they do require unmanaged code permissions.

--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

Ben Terry said:
Thanks for the help, John. I've tried what you suggested:

MemoryStream ms = new MemoryStream(m_ReceivedBytes);
BinaryFormatter bf = new BinaryFormatter();
m_CompleteIllumStateMsg = (MIX_CompleteIllumStateMsg)bf.Deserialize(ms);

Where m_ReceivedBytes is a byte[] and m_CompleteIllumStateMsg is my
structure. I get the following exception when I try to Deserialize:
"BinaryFormatter Version incompatibility. Expected Version 1.0. Received
Version 43.0." } System.Exception
Any thoughts on how to resolve this?

Ben

Sorry you wanted the reverse... in which case you can create a
MemoryStream
on the byte[] and use the Deserialize method of the BinaryFormatter to
create the struct from the buffer.

--
John Wood
EMail: first name, dot, second name at priorganize.com


What's the most efficient way to transfer data from a byte[] to a
struct?
The struct is rather complex--contains other structs as well as byte[]
members. I've tried to use Marshal.Copy and an IntPtr to my struct
address
but I get the following error, perhaps due to the byte[] members
of
 
Hi,
inline

Ben Terry said:
I'm still not sure this is the right way to do it. Here's some more
information on the structs I am trying to build from the byte[].

The structure contains nested structures. The nested structures are
interesting because they are defined in a COM type library. I am using them
in my C# project by means of the tlbimp.exe that converts a COM type library
into a common language runtime assembly. I am referencing this assembly in
my C# project. The byte arrays in the nested structures are defined, for
example, as:

BYTE strBarcode[32]; // This is in the idl file that is compiled to COM
type library.

It's decorated with [MarshalAs(UnmanagedType.ByValArray,SizeConst=32)],
probely you can't see this in object browser. You should see something like
'fixed array [32]' when using ildasm.

So if you do declare any arrays yourself you should do the same (prefix it
with MarshalAs as above). And prefix your structs with
[StructLayout(LayoutKind.Sequential)].

To do the actually marshalling:

byte[] dataIn = .....;
GCHandle hDataIn = GCHandle.Alloc(dataIn, GCHandleType.Pinned);
YourStruct ys =
(YourStruct)Marshal.PtrToStructure(hDataIn.AddrOfPinnedObject(),
typeof(YourStruct));
hDataIn.Free();
//work with ys
//...

You can't always just copy the bytes, because managed layout may differ from
the unmanaged one (not for byte arrays, but eg. for strings), which is
referred to as blittable or non-blittable types respectively.


HTH,
greetings

When I inspect these members in the object viewer after importing the
library into a runtime assembly they show up as, for example:

public byte[] strBarcode

I convert the structures to byte arrays in a C++ server program running on a
remote machine, and my C# client app reads them in and HOPEFULLY someday
will be able to fill up a struct identical to the one it originated from.

The CLR should know how big strBarcode is, right? If it does, I can't
understand why I can't simply do something like:

unsafe
{
MyStruct* p = &MyStruct;
Marshal.Copy(byteArray, (IntPtr)p, ....)
}

When I try code like this the compiler complains that I am trying to use the
address of a managed struct. If I remove those byte[] members from the
struct, the code compiles fine.

So my question remains, how can I simply load up my structure from a byte
stream? This seems like it should be so easy!

Ben

Justin Rogers said:
What John suggested only works if the byte[] contains serialized
data. What you actually want to look at is unsafe code. You can
use MarshalPtrToStructure and MarshalStructureToPtr as long as
your struct has layout information.

Note the above two methods aren't necessarily unsafe because the
CLR implements them for you, but they do require high privs, and
if I'm not mistaken they do require unmanaged code permissions.

--
Justin Rogers
DigiTec Web Consultants, LLC.
Blog: http://weblogs.asp.net/justin_rogers

Ben Terry said:
Thanks for the help, John. I've tried what you suggested:

MemoryStream ms = new MemoryStream(m_ReceivedBytes);
BinaryFormatter bf = new BinaryFormatter();
m_CompleteIllumStateMsg = (MIX_CompleteIllumStateMsg)bf.Deserialize(ms);

Where m_ReceivedBytes is a byte[] and m_CompleteIllumStateMsg is my
structure. I get the following exception when I try to Deserialize:
"BinaryFormatter Version incompatibility. Expected Version 1.0. Received
Version 43.0." } System.Exception
Any thoughts on how to resolve this?

Ben

Sorry you wanted the reverse... in which case you can create a
MemoryStream
on the byte[] and use the Deserialize method of the BinaryFormatter to
create the struct from the buffer.

--
John Wood
EMail: first name, dot, second name at priorganize.com


What's the most efficient way to transfer data from a byte[] to a
struct?
The struct is rather complex--contains other structs as well as byte[]
members. I've tried to use Marshal.Copy and an IntPtr to my struct
address
but I get the following error, perhaps due to the byte[] members
of
 

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

Back
Top