I am using the excellent VLC wrapper created by Roman Ginzburg re: nVLC
This part of his code returns a bitmap object.
In myh calling code I then convert it to a byte array.
I sthere a way to directly convert the memory pointer to a byte array with converting to a bitmap object.
this is his code:
unsafe void OnpDisplay(void* opaque, void* picture)
{
lock (m_lock)
{
PixelData* px = (PixelData*)opaque;
MemoryHeap.CopyMemory(m_pBuffer, px->pPixelData, px->size);
m_frameRate++;
if (m_callback != null)
{
using (Bitmap frame = GetBitmap())
{
m_callback(frame);
}
}
}
}
private Bitmap GetBitmap()
{
return new Bitmap(m_format.Width, m_format.Height, m_format.Pitch, m_format.PixelFormat, new IntPtr(m_pBuffer));
}
What I would like is another function like:
private byte[] GetBytes()
{
//not sure what to put here...
}
I am lookinga s I type but still cannot find anything or even if it possible to do so...
Thanks
Use Marshal.Copy. Like this:
private byte[] GetBytes() {
byte[] bytes = new byte[size];
Marshal.Copy(m_pBuffer, bytes, 0, size);
return bytes;
}
I'm not quite sure where you are storing the size of the buffer, but you must know that.
An aside. Why do you write new IntPtr(m_pBuffer) in GetBitmap rather than plain m_pBuffer?
I also wonder why you feel the need to use unsafe code here. Is it really needed?
Related
I'm trying to fill a structure (does not have to be an actual struct), with data loaded from a byte[].
There are many different data structures in the byte[], one of them is a string, which is declared as:
UInt16 stringLenght
byte[stringLenght] zeroTerminatedString
I 'c' language this could be handled by declaring a fixed size struct, and instead of a the struct containing the actual string, make a pointer to the string.
Something like:
UInt16 stringLength
char* zeroTerminatedString
Is there a (smart) way to do something similar in c#? I mean loading binary data from a file/memory and filling it into a structure?
Regards
Jakob Justesen
That's not how you'd declare it in C. If the record in the file contains a string then you'd declare the structure similar to:
struct Example {
int mumble; // Anything, not necessarily a string length
char text[42];
// etc...
};
The equivalent C# declaration would look like:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct Example {
public int mumble;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
public string text;
// etc...
}
You'd normally use BinaryReader to read the data. But it cannot handle strings like this directly, you have to read them as a byte[] and do the string conversion yourself. You also cannot take advantage of the declarative syntax, you have to write a call for each individual member of the struct.
There's a workaround for that, the Marshal class already knows how to convert unmanaged structures to managed ones with the PtrToStructure() method. Here's a generic implementation, it works for any blittable type. Two versions, a static one that reads from a byte[] and an instance method that was optimized to repeatedly read from a stream. You'd use a FileStream or MemoryStream with that one.
using System;
using System.IO;
using System.Runtime.InteropServices;
class StructTranslator {
public static bool Read<T>(byte[] buffer, int index, ref T retval) {
if (index == buffer.Length) return false;
int size = Marshal.SizeOf(typeof(T));
if (index + size > buffer.Length) throw new IndexOutOfRangeException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
IntPtr addr = (IntPtr)((long)handle.AddrOfPinnedObject() + index);
retval = (T)Marshal.PtrToStructure(addr, typeof(T));
}
finally {
handle.Free();
}
return true;
}
public bool Read<T>(Stream stream, ref T retval) {
int size = Marshal.SizeOf(typeof(T));
if (buffer == null || size > buffer.Length) buffer = new byte[size];
int len = stream.Read(buffer, 0, size);
if (len == 0) return false;
if (len != size) throw new EndOfStreamException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
retval = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally {
handle.Free();
}
return true;
}
private byte[] buffer;
}
Untested, hope it works.
The Marshal should be able to do this for you.
Note that this can only be done to a struct and you will probably need to use the StructLayout attribute.
I'm not 100% sure on how to handle the string or arrays, but BStrWrapper or ArrayWithOffset MIGHT help, also keep on the lookout for similar classes/attributes (I know I have done stuff like this before for binding to native functions).
I read following some where. Can somebody shed some light on it probably with an example
'the message could even be a struct that is just converted to a byte array which is outputted on the debug UART.
Then on the PC side, the incoming byte array can be easily converted back to a struct like object.'
You can use unsafe to access any blittable (arrays, strings, structs etc.) types as a byte pointer.
Local variables of value types don't have to be pinned:
public unsafe void ReadAsBytePointer(MyStruct obj)
{
byte* ptr = (byte*)&obj;
...
}
Arrays must be pinned. The easiest solution is to use fixed:
public unsafe void ReadAsBytePointer(MyStruct[] input)
{
fixed(MyStruct* ptr = input)
{
byte* byteArray = (byte*)ptr;
}
}
For a general case without adding unsafe to your code you can use GCHandle:
static byte[] GetBytes<T>(T input)
where T : struct
{
int size = Marshal.SizeOf(typeof(T));
byte[] result = new byte[size];
GCHandle gc = GCHandle.Alloc(input, GCHandleType.Pinned);
try
{
Marshal.Copy(gc.AddrOfPinnedObject(), result, 0, size);
}
finally
{
gc.Free();
}
return result;
}
I'm trying to fill a structure (does not have to be an actual struct), with data loaded from a byte[].
There are many different data structures in the byte[], one of them is a string, which is declared as:
UInt16 stringLenght
byte[stringLenght] zeroTerminatedString
I 'c' language this could be handled by declaring a fixed size struct, and instead of a the struct containing the actual string, make a pointer to the string.
Something like:
UInt16 stringLength
char* zeroTerminatedString
Is there a (smart) way to do something similar in c#? I mean loading binary data from a file/memory and filling it into a structure?
Regards
Jakob Justesen
That's not how you'd declare it in C. If the record in the file contains a string then you'd declare the structure similar to:
struct Example {
int mumble; // Anything, not necessarily a string length
char text[42];
// etc...
};
The equivalent C# declaration would look like:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct Example {
public int mumble;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
public string text;
// etc...
}
You'd normally use BinaryReader to read the data. But it cannot handle strings like this directly, you have to read them as a byte[] and do the string conversion yourself. You also cannot take advantage of the declarative syntax, you have to write a call for each individual member of the struct.
There's a workaround for that, the Marshal class already knows how to convert unmanaged structures to managed ones with the PtrToStructure() method. Here's a generic implementation, it works for any blittable type. Two versions, a static one that reads from a byte[] and an instance method that was optimized to repeatedly read from a stream. You'd use a FileStream or MemoryStream with that one.
using System;
using System.IO;
using System.Runtime.InteropServices;
class StructTranslator {
public static bool Read<T>(byte[] buffer, int index, ref T retval) {
if (index == buffer.Length) return false;
int size = Marshal.SizeOf(typeof(T));
if (index + size > buffer.Length) throw new IndexOutOfRangeException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
IntPtr addr = (IntPtr)((long)handle.AddrOfPinnedObject() + index);
retval = (T)Marshal.PtrToStructure(addr, typeof(T));
}
finally {
handle.Free();
}
return true;
}
public bool Read<T>(Stream stream, ref T retval) {
int size = Marshal.SizeOf(typeof(T));
if (buffer == null || size > buffer.Length) buffer = new byte[size];
int len = stream.Read(buffer, 0, size);
if (len == 0) return false;
if (len != size) throw new EndOfStreamException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
retval = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally {
handle.Free();
}
return true;
}
private byte[] buffer;
}
Untested, hope it works.
The Marshal should be able to do this for you.
Note that this can only be done to a struct and you will probably need to use the StructLayout attribute.
I'm not 100% sure on how to handle the string or arrays, but BStrWrapper or ArrayWithOffset MIGHT help, also keep on the lookout for similar classes/attributes (I know I have done stuff like this before for binding to native functions).
Can anyone tell me how to get a array of bytes into a structure in a direct fashion in C# .NET version 2? Like the familiar fread as found in C, so far I have not had much success in reading a stream of bytes and automatically filling a structure. I have seen some implementations where there is pointer hocus-pocus in the managed code by using the unsafe keyword.
Have a look at this sample:
public unsafe struct foobarStruct{
/* fields here... */
public foobarStruct(int nFakeArgs){
/* Initialize the fields... */
}
public foobarStruct(byte[] data) : this(0) {
unsafe {
GCHandle hByteData = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr pByteData = hByteData.AddrOfPinnedObject();
this = (foobarStruct)Marshal.PtrToStructure(pByteData, this.GetType());
hByteData.Free();
}
}
}
The reason I have two constructors in foobarStruct
Is there cannot be an empty constructor.
Pass in a block of memory (as a byte array) into the constructor when instantiating the structure.
Is that implementation good enough or is there a much cleaner way to achieve this?
Edit: I do not want to use the ISerializable interface or its implementation.
I am trying to read a binary image to work out the fields used and determine its data using the PE structures.
There isn't anything wrong with using the P/Invoke marshaller, it is not unsafe and you don't have to use the unsafe keyword. Getting it wrong will just produce bad data. It can be a lot easier to use than explicitly writing the deserialization code, especially when the file contains strings. You can't use BinaryReader.ReadString(), it assumes that the string was written by BinaryWriter. Make sure however that you declare the structure of the data with a struct declaration, this.GetType() is not likely to work out well.
Here's a generic class that will make it work for any structure declaration:
class StructureReader<T> where T : struct {
private byte[] mBuffer;
public StructureReader() {
mBuffer = new byte[Marshal.SizeOf(typeof(T))];
}
public T Read(System.IO.FileStream fs) {
int bytes = fs.Read(mBuffer, 0, mBuffer.Length);
if (bytes == 0) throw new InvalidOperationException("End-of-file reached");
if (bytes != mBuffer.Length) throw new ArgumentException("File contains bad data");
T retval;
GCHandle hdl = GCHandle.Alloc(mBuffer, GCHandleType.Pinned);
try {
retval = (T)Marshal.PtrToStructure(hdl.AddrOfPinnedObject(), typeof(T));
}
finally {
hdl.Free();
}
return retval;
}
A sample declaration for the structure of the data in the file:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct Sample {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
public string someString;
}
You'll need to tweak the structure declaration and the attributes to get a match with the data in the file. Sample code that reads a file:
var data = new List<Sample>();
var reader = new StructureReader<Sample>();
using (var stream = new FileStream(#"c:\temp\test.bin", FileMode.Open, FileAccess.Read)) {
while(stream.Position < stream.Length) {
data.Add(reader.Read(stream));
}
}
You probably want to use a BinaryReader which allows you to read in primitive types in binary form.
Create a MemoryStream from the byte[] and then use the BinaryReader from that. You should be able to read out the structure and fill in your object accordingly.
I want to pass a byte[] to a method takes a IntPtr Parameter in C#, is that possible and how?
Another way,
GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();
The following should work but must be used within an unsafe context:
byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
// Do your stuff here
}
Beware: you have to use the pointer within the fixed block. The GC can move the object once you are no longer within the fixed block.
Not sure about getting an IntPtr to an array, but you can copy the data for use with unmanaged code by using Mashal.Copy:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
Alternatively you could declare a struct with one property and then use Marshal.PtrToStructure, but that would still require allocating unmanaged memory.
Edit: Also, as Tyalis pointed out, you can also use fixed if unsafe code is an option for you
You could use Marshal.UnsafeAddrOfPinnedArrayElement to get a memory pointer to the array (or to a specific element in the array). Keep in mind that the array must be pinned first as per the API documentation:
The array must be pinned using a GCHandle before it is passed to this method. For maximum performance, this method does not validate the array passed to it; this can result in unexpected behavior.
Here's a twist on #user65157's answer (+1 for that, BTW):
I created an IDisposable wrapper for the pinned object:
class AutoPinner : IDisposable
{
GCHandle _pinnedArray;
public AutoPinner(Object obj)
{
_pinnedArray = GCHandle.Alloc(obj, GCHandleType.Pinned);
}
public static implicit operator IntPtr(AutoPinner ap)
{
return ap._pinnedArray.AddrOfPinnedObject();
}
public void Dispose()
{
_pinnedArray.Free();
}
}
then use it like thusly:
using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr
//do your stuff
}
I found this to be a nice way of not forgetting to call Free() :)
Marshal.Copy works but is rather slow. Faster is to copy the bytes in a for loop. Even faster is to cast the byte array to a ulong array, copy as much ulong as fits in the byte array, then copy the possible remaining 7 bytes (the trail that is not 8 bytes aligned). Fastest is to pin the byte array in a fixed statement as proposed above in Tyalis' answer.
In some cases you can use an Int32 type (or Int64) in case of the IntPtr. If you can, another useful class is BitConverter. For what you want you could use BitConverter.ToInt32 for example.