PtrToStructure for unknown structure?

C

carles

Hi,

Here, sample code where a byte array is used to fill a particular structure:

[...]

fs = File.OpenRead(path); // FileStream

BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
b = new byte[(int)bfh.Size()];

fs.Read(b, 0, b.Length);
fixed (byte* pb = &b[0])
bfh = (BITMAPFILEHEADER)Marshal.PtrToStructure((IntPtr)pb, typeof(BITMAPFILEHEADER));

[...]

What I would like to have is a function capable of accepting an [in] byte array and an [out] unkown structure type.
Is that possible?

Thanks in advance,

Carles
 
B

baretta

Using a generic method that takes a type parameter:
public static unsafe T ByteArrayToStructure<T> ( byte [ ] array )
where T : struct
{
fixed ( byte* pb = &b [ 0 ] )
return ( T ) Marshal.PtrToStructure( (IntPtr)pb, typeof(T));
}

If you are using unsafe anyway, you dont need to use Marshal if you dont
want to,
you could cast it old C++ style if you want. Probably more efficient

Dennis Myren


Hi,

Here, sample code where a byte array is used to fill a particular structure:

[...]

fs = File.OpenRead(path); // FileStream

BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
b = new byte[(int)bfh.Size()];

fs.Read(b, 0, b.Length);
fixed (byte* pb = &b[0])
bfh =
(BITMAPFILEHEADER)Marshal.PtrToStructure((IntPtr)pb,
typeof(BITMAPFILEHEADER));

[...]

What I would like to have is a function capable of accepting an [in] byte
array and an [out] unkown structure type.
Is that possible?

Thanks in advance,

Carles
 
C

carles

Thanks a lot,

New on "C#" (and C)... could you please tell me how to do it old C++ style?

Carles
 
B

baretta

I am sorry if i was misleading.


Actually it is not possible to use a C-style approach,
it would only work with structure whose types we know during compile time.

This approach was what i was thinking about(without really thinking):
public static unsafe T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
fixed ( byte* pBuff = buffer )
{
return *( T* ) pBuff;
}
}

But actually, although we limit T to being a struct using where keyword,
we cannot at this point guarantee that a pointer to this type can be
obtained at runtime.
It can only be obtained if a struct has only primitive fields, and this we
cant guarantee at this point.
If we would change the return value to a known struct made up completely of
primitives it would compile.


This one is totally managed. At least it compiles:
public static T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
IntPtr ptr = Marshal.AllocHGlobal ( buffer.Length );
Marshal.Copy ( buffer, 0x0, ptr, buffer.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}

and you will use it like this:
BITMAPFILEHEADER header = ByteArrayToStructure<BITMAPFILEHEADER> (
yourByteArray );


I would recommend modifying ByteArrayToStructure, so that it takes the
System.IO.Stream as parameter rather than the byte array.
Otherwise, it is assumed that the buffer passed in is of the correct size
already(which is the size of the struct).
It is better if this is handled by the function.

So, this is the final result:
public static T ReadStructure<T> ( Stream stream )
where T : struct
{
byte [ ] buff = new byte [ Marshal.SizeOf ( typeof ( T ) ) ];
IntPtr ptr = Marshal.AllocHGlobal ( buff.Length );
Marshal.Copy ( buff, 0x0, ptr, buff.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}


Dennis Myren


carles said:
Thanks a lot,

New on "C#" (and C)... could you please tell me how to do it old C++
style?

Carles

baretta said:
Using a generic method that takes a type parameter:
public static unsafe T ByteArrayToStructure<T> ( byte [ ] array )
where T : struct
{
fixed ( byte* pb = &b [ 0 ] )
return ( T ) Marshal.PtrToStructure( (IntPtr)pb, typeof(T));
}

If you are using unsafe anyway, you dont need to use Marshal if you dont
want to,
you could cast it old C++ style if you want. Probably more efficient

Dennis Myren


Hi,

Here, sample code where a byte array is used to fill a particular
structure:

[...]

fs = File.OpenRead(path); // FileStream

BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
b = new byte[(int)bfh.Size()];

fs.Read(b, 0, b.Length);
fixed (byte* pb = &b[0])
bfh =
(BITMAPFILEHEADER)Marshal.PtrToStructure((IntPtr)pb,
typeof(BITMAPFILEHEADER));

[...]

What I would like to have is a function capable of accepting an [in] byte
array and an [out] unkown structure type.
Is that possible?

Thanks in advance,

Carles
 
C

carles

Thanks again.
Really enlightening answer.

One thing: Marshal.SizeOf() seems to return 32-bit (depends on what?)
aligned sizes.
In my case, I sequentially read several structures from file, so I need to
exactly read structure byte-lenghts (ie, BITMAPFILEHEADER is 14
byte-lenght). I decided to add a static Size() function for each structure
definition, returning its byte-lenght size. Error handling is done at time
to read from file.

So, another question could be next: how to determine byte-length size of the
passed (unknown) structure. This would allow to compact ByteArrayToStructure
to your suggested final approach, sizing buffer and reading from stream
inside same function.

Carles

baretta said:
I am sorry if i was misleading.


Actually it is not possible to use a C-style approach,
it would only work with structure whose types we know during compile time.

This approach was what i was thinking about(without really thinking):
public static unsafe T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
fixed ( byte* pBuff = buffer )
{
return *( T* ) pBuff;
}
}

But actually, although we limit T to being a struct using where keyword,
we cannot at this point guarantee that a pointer to this type can be
obtained at runtime.
It can only be obtained if a struct has only primitive fields, and this we
cant guarantee at this point.
If we would change the return value to a known struct made up completely
of primitives it would compile.


This one is totally managed. At least it compiles:
public static T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
IntPtr ptr = Marshal.AllocHGlobal ( buffer.Length );
Marshal.Copy ( buffer, 0x0, ptr, buffer.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}

and you will use it like this:
BITMAPFILEHEADER header = ByteArrayToStructure<BITMAPFILEHEADER> (
yourByteArray );


I would recommend modifying ByteArrayToStructure, so that it takes the
System.IO.Stream as parameter rather than the byte array.
Otherwise, it is assumed that the buffer passed in is of the correct size
already(which is the size of the struct).
It is better if this is handled by the function.

So, this is the final result:
public static T ReadStructure<T> ( Stream stream )
where T : struct
{
byte [ ] buff = new byte [ Marshal.SizeOf ( typeof ( T ) ) ];
IntPtr ptr = Marshal.AllocHGlobal ( buff.Length );
Marshal.Copy ( buff, 0x0, ptr, buff.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}


Dennis Myren


carles said:
Thanks a lot,

New on "C#" (and C)... could you please tell me how to do it old C++
style?

Carles

baretta said:
Using a generic method that takes a type parameter:
public static unsafe T ByteArrayToStructure<T> ( byte [ ] array )
where T : struct
{
fixed ( byte* pb = &b [ 0 ] )
return ( T ) Marshal.PtrToStructure( (IntPtr)pb, typeof(T));
}

If you are using unsafe anyway, you dont need to use Marshal if you dont
want to,
you could cast it old C++ style if you want. Probably more efficient

Dennis Myren


Hi,

Here, sample code where a byte array is used to fill a particular
structure:

[...]

fs = File.OpenRead(path); // FileStream

BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
b = new byte[(int)bfh.Size()];

fs.Read(b, 0, b.Length);
fixed (byte* pb = &b[0])
bfh =
(BITMAPFILEHEADER)Marshal.PtrToStructure((IntPtr)pb,
typeof(BITMAPFILEHEADER));

[...]

What I would like to have is a function capable of accepting an [in]
byte array and an [out] unkown structure type.
Is that possible?

Thanks in advance,

Carles
 
C

carles

At structure definition, for example:

[StructLayout(LayoutKind.Sequential, Pack=1)]
private struct BITMAPFILEHEADER
{
public ushort bfType;
public uint bfSize;
public short bfReserved1;
public short bfReserved2;
public uint bfOffBits;
}

adding that 'Pack=1 specification', no padding is done, and 'packed' size is
returned, 14.
Hope nothing more has to be taken into account.

Carles


carles said:
Thanks again.
Really enlightening answer.

One thing: Marshal.SizeOf() seems to return 32-bit (depends on what?)
aligned sizes.
In my case, I sequentially read several structures from file, so I need to
exactly read structure byte-lenghts (ie, BITMAPFILEHEADER is 14
byte-lenght). I decided to add a static Size() function for each structure
definition, returning its byte-lenght size. Error handling is done at time
to read from file.

So, another question could be next: how to determine byte-length size of
the passed (unknown) structure. This would allow to compact
ByteArrayToStructure to your suggested final approach, sizing buffer and
reading from stream inside same function.

Carles

baretta said:
I am sorry if i was misleading.


Actually it is not possible to use a C-style approach,
it would only work with structure whose types we know during compile
time.

This approach was what i was thinking about(without really thinking):
public static unsafe T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
fixed ( byte* pBuff = buffer )
{
return *( T* ) pBuff;
}
}

But actually, although we limit T to being a struct using where keyword,
we cannot at this point guarantee that a pointer to this type can be
obtained at runtime.
It can only be obtained if a struct has only primitive fields, and this
we cant guarantee at this point.
If we would change the return value to a known struct made up completely
of primitives it would compile.


This one is totally managed. At least it compiles:
public static T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
IntPtr ptr = Marshal.AllocHGlobal ( buffer.Length );
Marshal.Copy ( buffer, 0x0, ptr, buffer.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}

and you will use it like this:
BITMAPFILEHEADER header = ByteArrayToStructure<BITMAPFILEHEADER> (
yourByteArray );


I would recommend modifying ByteArrayToStructure, so that it takes the
System.IO.Stream as parameter rather than the byte array.
Otherwise, it is assumed that the buffer passed in is of the correct size
already(which is the size of the struct).
It is better if this is handled by the function.

So, this is the final result:
public static T ReadStructure<T> ( Stream stream )
where T : struct
{
byte [ ] buff = new byte [ Marshal.SizeOf ( typeof ( T ) ) ];
IntPtr ptr = Marshal.AllocHGlobal ( buff.Length );
Marshal.Copy ( buff, 0x0, ptr, buff.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}


Dennis Myren


carles said:
Thanks a lot,

New on "C#" (and C)... could you please tell me how to do it old C++
style?

Carles

"baretta" <[email protected]> ha escrit al missatge del grup de
discussió: (e-mail address removed)...
Using a generic method that takes a type parameter:
public static unsafe T ByteArrayToStructure<T> ( byte [ ] array )
where T : struct
{
fixed ( byte* pb = &b [ 0 ] )
return ( T ) Marshal.PtrToStructure( (IntPtr)pb, typeof(T));
}

If you are using unsafe anyway, you dont need to use Marshal if you
dont want to,
you could cast it old C++ style if you want. Probably more efficient

Dennis Myren


Hi,

Here, sample code where a byte array is used to fill a particular
structure:

[...]

fs = File.OpenRead(path); // FileStream

BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
b = new byte[(int)bfh.Size()];

fs.Read(b, 0, b.Length);
fixed (byte* pb = &b[0])
bfh =
(BITMAPFILEHEADER)Marshal.PtrToStructure((IntPtr)pb,
typeof(BITMAPFILEHEADER));

[...]

What I would like to have is a function capable of accepting an [in]
byte array and an [out] unkown structure type.
Is that possible?

Thanks in advance,

Carles
 
B

baretta

That is correct, i have used both Marshal.SizeOf and the unsafe keyword
sizeof myself to retrieve sizes of structures correctly.
All my structures has the Pack=1 property set.

You should be OK.




carles said:
At structure definition, for example:

[StructLayout(LayoutKind.Sequential, Pack=1)]
private struct BITMAPFILEHEADER
{
public ushort bfType;
public uint bfSize;
public short bfReserved1;
public short bfReserved2;
public uint bfOffBits;
}

adding that 'Pack=1 specification', no padding is done, and 'packed' size
is returned, 14.
Hope nothing more has to be taken into account.

Carles


carles said:
Thanks again.
Really enlightening answer.

One thing: Marshal.SizeOf() seems to return 32-bit (depends on what?)
aligned sizes.
In my case, I sequentially read several structures from file, so I need
to exactly read structure byte-lenghts (ie, BITMAPFILEHEADER is 14
byte-lenght). I decided to add a static Size() function for each
structure definition, returning its byte-lenght size. Error handling is
done at time to read from file.

So, another question could be next: how to determine byte-length size of
the passed (unknown) structure. This would allow to compact
ByteArrayToStructure to your suggested final approach, sizing buffer and
reading from stream inside same function.

Carles

baretta said:
I am sorry if i was misleading.


Actually it is not possible to use a C-style approach,
it would only work with structure whose types we know during compile
time.

This approach was what i was thinking about(without really thinking):
public static unsafe T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
fixed ( byte* pBuff = buffer )
{
return *( T* ) pBuff;
}
}

But actually, although we limit T to being a struct using where keyword,
we cannot at this point guarantee that a pointer to this type can be
obtained at runtime.
It can only be obtained if a struct has only primitive fields, and this
we cant guarantee at this point.
If we would change the return value to a known struct made up completely
of primitives it would compile.


This one is totally managed. At least it compiles:
public static T ByteArrayToStructure<T> ( byte [ ] buffer )
where T : struct
{
IntPtr ptr = Marshal.AllocHGlobal ( buffer.Length );
Marshal.Copy ( buffer, 0x0, ptr, buffer.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}

and you will use it like this:
BITMAPFILEHEADER header = ByteArrayToStructure<BITMAPFILEHEADER> (
yourByteArray );


I would recommend modifying ByteArrayToStructure, so that it takes the
System.IO.Stream as parameter rather than the byte array.
Otherwise, it is assumed that the buffer passed in is of the correct
size already(which is the size of the struct).
It is better if this is handled by the function.

So, this is the final result:
public static T ReadStructure<T> ( Stream stream )
where T : struct
{
byte [ ] buff = new byte [ Marshal.SizeOf ( typeof ( T ) ) ];
IntPtr ptr = Marshal.AllocHGlobal ( buff.Length );
Marshal.Copy ( buff, 0x0, ptr, buff.Length );
T ret = ( T ) Marshal.PtrToStructure ( ptr, typeof ( T ) );

Marshal.FreeHGlobal ( ptr );
return ret;
}


Dennis Myren


"carles" <[email protected]> skrev i melding
Thanks a lot,

New on "C#" (and C)... could you please tell me how to do it old C++
style?

Carles

"baretta" <[email protected]> ha escrit al missatge del grup de
discussió: (e-mail address removed)...
Using a generic method that takes a type parameter:
public static unsafe T ByteArrayToStructure<T> ( byte [ ] array )
where T : struct
{
fixed ( byte* pb = &b [ 0 ] )
return ( T ) Marshal.PtrToStructure( (IntPtr)pb, typeof(T));
}

If you are using unsafe anyway, you dont need to use Marshal if you
dont want to,
you could cast it old C++ style if you want. Probably more efficient

Dennis Myren


Hi,

Here, sample code where a byte array is used to fill a particular
structure:

[...]

fs = File.OpenRead(path); // FileStream

BITMAPFILEHEADER bfh = new BITMAPFILEHEADER();
b = new byte[(int)bfh.Size()];

fs.Read(b, 0, b.Length);
fixed (byte* pb = &b[0])
bfh =
(BITMAPFILEHEADER)Marshal.PtrToStructure((IntPtr)pb,
typeof(BITMAPFILEHEADER));

[...]

What I would like to have is a function capable of accepting an [in]
byte array and an [out] unkown structure type.
Is that possible?

Thanks in advance,

Carles
 

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