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