By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,916 Members | 1,316 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,916 IT Pros & Developers. It's quick & easy.

Structure to Byte Array in VB.NET

P: n/a
I have been pulling my hair out with this and have searched and found
some solutions but I can't seem to get them to work as expected.

I have a structure, which I have declared explicitly using
<StructLayout(LayoutKind.Explicit)>

The structure does contain some arrays, but it is something like this

<StructLayout(LayoutKind.Explicit)>
Public Structure TheStruct
<FieldOffset(0)Dim UpdateMode As Int16
<FieldOffset(2)Dim TimeFrameCounter As Int16
<FieldOffset(4), VBFixedArray(7)Dim AxisCommandedPosition() As
Integer
<FieldOffset(36), VBFixedArray(7)Dim AxisEncoderPosition() As
Integer
<FieldOffset(68), VBFixedArray(7)Dim AxisCommandedVelocity() As
Integer
<FieldOffset(100), VBFixedArray(7)Dim AxisStatus() As Integer
<FieldOffset(132)Dim SystemStatus As Integer
End Structure

I need to use this as a byte array so I can send it over a ethernet
socket (after manipulating it a bit)

I have tried this:
Dim myStruct as TheStruct
Dim fsdata() As Byte
ReDim fsdata(Marshal.SizeOf(myStruct) - 1)
Dim ptr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(myStruct))

'get a pointer to myStruct
Marshal.StructureToPtr(myStruct, ptr, True)

'copy myStruct from the heap pointer into fsdata array
Marshal.Copy(ptr, fsdata, 0, Marshal.SizeOf(myStruct))

'release the heap memory
Marshal.FreeHGlobal(ptr)

This sometimes works, but the line
Marshal.StructureToPtr(myStruct, ptr, True)
often crashes with a message "Attempted to read or write protected
memory."
If I change it to:
Marshal.StructureToPtr(myStruct, ptr, False)
It doesnt crash, but the data that ends up in the fsdata data is
garbage - not myStruct.

Is there a way to do this in vb.net that actually works?

If I have a managed structure of a fixed size explicitly laid out, why
do I have to marshal it through unmanaged memory to use it as a byte
array?

When I call Marshal.AllocHGlobal to get a pointer why would it give me
a pointer to a protected memory area I can't use? Or is that what is
happening?

For now I have given up on using the structure and will just use a
byte array. I will write some other functions to access the peices of
the array as if it were a structure, but this is messy.

Is there a better way?

thanks.
Dec 14 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
><StructLayout(LayoutKind.Explicit)>
>Public Structure TheStruct
<FieldOffset(0)Dim UpdateMode As Int16
<FieldOffset(2)Dim TimeFrameCounter As Int16
<FieldOffset(4), VBFixedArray(7)Dim AxisCommandedPosition() As
Integer
<FieldOffset(36), VBFixedArray(7)Dim AxisEncoderPosition() As
Integer
<FieldOffset(68), VBFixedArray(7)Dim AxisCommandedVelocity() As
Integer
<FieldOffset(100), VBFixedArray(7)Dim AxisStatus() As Integer
<FieldOffset(132)Dim SystemStatus As Integer
End Structure
The CLR marshaler doesn't understand the VBFixedArray attribute. Try
adding <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)>.

>If I have a managed structure of a fixed size explicitly laid out, why
do I have to marshal it through unmanaged memory to use it as a byte
array?
Because in the strongly typed world of .NET, you can't treat an object
of a certain type (the structure) as an entirely different type (the
byte array) even if they happen to share the same memory layout.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Dec 14 '07 #2

P: n/a
Can't you just write a TheStruct.ToByteArray() function and manually convert
the structure members to Bytes?

If you are a bit lazy like me and performance is not an issue you can also
use a BinaryWriter on a MemoryStream then use the MemoryStream.ToArray()
function. Saves you having to manually lay out your integers etc. You'll
still need to loop through your arrays though.

Microsoft have always made it difficult to convert variables to and from raw
bytes in BASIC. PEEK() and POKE() are long gone!

-David

"Mattias Sjögren" wrote:
<StructLayout(LayoutKind.Explicit)>
Public Structure TheStruct
<FieldOffset(0)Dim UpdateMode As Int16
<FieldOffset(2)Dim TimeFrameCounter As Int16
<FieldOffset(4), VBFixedArray(7)Dim AxisCommandedPosition() As
Integer
<FieldOffset(36), VBFixedArray(7)Dim AxisEncoderPosition() As
Integer
<FieldOffset(68), VBFixedArray(7)Dim AxisCommandedVelocity() As
Integer
<FieldOffset(100), VBFixedArray(7)Dim AxisStatus() As Integer
<FieldOffset(132)Dim SystemStatus As Integer
End Structure

The CLR marshaler doesn't understand the VBFixedArray attribute. Try
adding <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)>.

If I have a managed structure of a fixed size explicitly laid out, why
do I have to marshal it through unmanaged memory to use it as a byte
array?

Because in the strongly typed world of .NET, you can't treat an object
of a certain type (the structure) as an entirely different type (the
byte array) even if they happen to share the same memory layout.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Dec 18 '07 #3

P: n/a
I've recently discovered the BitConverter class which might also help you.
----------------
David Streeter
Synchrotech Software
Sydney Australia
"surturz" wrote:
Can't you just write a TheStruct.ToByteArray() function and manually convert
the structure members to Bytes?

If you are a bit lazy like me and performance is not an issue you can also
use a BinaryWriter on a MemoryStream then use the MemoryStream.ToArray()
function. Saves you having to manually lay out your integers etc. You'll
still need to loop through your arrays though.

Microsoft have always made it difficult to convert variables to and from raw
bytes in BASIC. PEEK() and POKE() are long gone!

-David

"Mattias Sjögren" wrote:
><StructLayout(LayoutKind.Explicit)>
>Public Structure TheStruct
<FieldOffset(0)Dim UpdateMode As Int16
<FieldOffset(2)Dim TimeFrameCounter As Int16
<FieldOffset(4), VBFixedArray(7)Dim AxisCommandedPosition() As
>Integer
<FieldOffset(36), VBFixedArray(7)Dim AxisEncoderPosition() As
>Integer
<FieldOffset(68), VBFixedArray(7)Dim AxisCommandedVelocity() As
>Integer
<FieldOffset(100), VBFixedArray(7)Dim AxisStatus() As Integer
<FieldOffset(132)Dim SystemStatus As Integer
>End Structure
The CLR marshaler doesn't understand the VBFixedArray attribute. Try
adding <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)>.

>If I have a managed structure of a fixed size explicitly laid out, why
>do I have to marshal it through unmanaged memory to use it as a byte
>array?
Because in the strongly typed world of .NET, you can't treat an object
of a certain type (the structure) as an entirely different type (the
byte array) even if they happen to share the same memory layout.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Jan 8 '08 #4

This discussion thread is closed

Replies have been disabled for this discussion.