A C# equivalent of C's fread file i/o - c#

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.

Related

How to free an array stored in heap returned from C++ DLL in c#?

I have a C++ DLL that reads a buffer and returns its content as a char array along with its size.
And I have a C# code that imports the DLL and it can read the array content and size created from C++, but it is causing a memory leak.
I am creating a dynamic array in heap from the C++ side and I know that after using new char[] I should use delete[] to free the array, but in this case I don't know how or where to put it or if it is possible to do it from C# side.
Here is my c++ side code. I tried putting only the important parts.
mystream.h
class MyStream {
public:
char* data;
ULONG size;
};
MyStream getStream(){
MyStream result;
result.size = getBufferSize(); // Gets the buffer size. The size is not constant so I cannot store the array in stack
result.data = new char[result.size]; // Creates a new char array, now knowing its size
ReadBuffer(result.data, result.size) // Reads a buffer and result.data now has the buffer content. Someting like this: ['a','b','c','d','e',...]
return result;
};
c++ export
#include "mystream.h"
MyStream getMyStream()
{
MyStream myStream = getStream();
return myStream;
// here if I use delete[] myStream.data it will take no effect
}
DLL export
extern "C"
{
DLLExport MyStream getMyStream();
}
And here is my c# side code.
public struct MyStream
{
public IntPtr Data;
public int Size;
}
[DllImport("my-stream")]
public static extern MyStream getMyStream();
public void ReadUsingTheDLL()
{
MyStream myStream = getMyStream();
byte[] byteStreamArray = new byte[myStream.Size]; // I can read the array size, all good
Marshal.Copy(myStream.Data, byteStreamArray, 0, myStream.Size); // I can read the array content in byteStreamArray, all good
// How do I free the memory from myStream.Data? since I am no longer using it
}

How to perform a minimal-allocation conversion of 'Memory<T>' into 'Stream'?

There doesn't seem to exist a native way of converting a Memory<T> instance into a Stream in the framework. Is there a simple way to achieve this using some allocation-free approach that only uses the actual memory from the Memory<T> instance, or perhaps a way that leverages only a minimal buffer?
I wasn't able to find any examples going from Memory<T> to Stream: only the opposite is common since there are several newer overloads on Stream that allow handling Memory<T> instances.
It seems so intuitive that one would be able to convert from Memory<> to MemoryStream (due mostly to their names, admittedly) so I was a bit disappointed to find this wasn't the case.
I also wasn't able to find any easy way of creating a System.IO.Pipelines PipeReader or PipeWriter with a Memory<T>, as those have a AsStream extension.
The thing is, the Memory<T> might not actually be looking at an array: it might be using a MemoryManager, or doing something else.
That said, it's possible to use MemoryMarshal.TryGetArray to see whether it does reference an array, and take an optimized path if so:
ReadOnlyMemory<byte> memory = new byte[] { 1, 2, 3, 4, 5 }.AsMemory();
var stream = MemoryMarshal.TryGetArray(memory, out var arraySegment)
? new MemoryStream(arraySegment.Array, arraySegment.Offset, arraySegment.Count)
: new MemoryStream(memory.ToArray());
You will need to use unsafe code:
private static unsafe void DoUnsafeMemoryStuff<T>(ReadOnlyMemory<T> mem) where T : unmanaged
{
Stream stream;
MemoryHandle? memHandle = null;
GCHandle? byteHandle = null;
int itemSize = sizeof(T);
if (MemoryMarshal.TryGetArray(memory, out var arr))
{
byteHandle = GCHandle.Alloc(arr.Array, GCHandleType.Pinned);
int offsetBytes = arr.Offset * itemSize;
int totalBytes = arr.Count * itemSize;
int streamBytesRemaining = totalBytes - offsetBytes;
stream = new UnmanagedMemoryStream((byte*)byteHandle.Pointer + offsetBytes, streamBytesRemaining);
}
else
{
// common path, will be very fast to get the stream setup
memHandle = mem.Pin();
stream = new UnmanagedMemoryStream((byte*)memHandle.Pointer, mem.Length * itemSize);
}
// use stream like any other stream - you will need to keep your memory object and the handle object alive until your stream usage is complete
try
{
// do stuff with stream
}
finally
{
// cleanup
if (memHandle.HasValue) { memHandle.Value.Dispose(); }
if (byteHandle.HasValue) { byteHandle.Value.Free(); }
}
}

Can I memory align data structures in C# to exactly match received messages like in C? [duplicate]

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).

Convert memory pointer to byte array

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?

loading binary data into a structure

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).

Categories

Resources