Reputation: 7166
I have a System.Array
of value struct types, something like this:
public value struct Position
{
int timestamp;
float x;
float y;
}
Position[] positions = new Position[1000 * 1000];
After I initialize the array with values, how can I get a byte[]
of it's content, without serializing one item at a time?
In C++/CLI I would use a pin_ptr
to get the pointer to the array content and I would copy the data from there. Can I do something like this in C#?
EDIT: I need to write the raw data to disk, as if it were a C struct, without any kind of serialization.
I tagged this question as C# for broader exposure, but actually I'm trying to serialize the data from IronPython, so this means I can't use any unsafe
C# functionality.
Upvotes: 2
Views: 880
Reputation: 1383
Here's a method that doesn't require unsafe code:
[Updated to remove the for loop and perform the copy in a single pass]
private static byte[] StructureToByteArray(Position[] posArray)
{
if (posArray == null || posArray.Length == 0)
{
return new byte[0];
}
var lenOfObject = Marshal.SizeOf(typeof(Position));
var len = lenOfObject * posArray.Length;
var arr = new byte[len];
var handle = GCHandle.Alloc(posArray, GCHandleType.Pinned);
try
{
var ptr = handle.AddrOfPinnedObject();
Marshal.Copy(ptr, arr, 0, len);
}
finally
{
handle.Free();
}
return arr;
}
Upvotes: 1
Reputation: 27495
I believe this is the equivalent to the C++/CLI pin_ptr using unsafe C# code:
public static unsafe byte[] GetBytes(Position[] positions)
{
byte[] result = new byte[positions.Length * Marshal.SizeOf(typeof(Position))];
fixed (Position* ptr = &positions[0])
{
Marshal.Copy((IntPtr)ptr, result, 0, result.Length);
}
return result;
}
Upvotes: 1
Reputation: 31239
Maybe this will help:
[Serializable()]
public struct Position
{
int timestamp;
float x;
float y;
}
static void Main(string[] args)
{
var positions = new Position[1000 * 1000];
GetBytes(positions);
}
private static byte[] GetBytes(object obj)
{
using (var memoryStream = new System.IO.MemoryStream())
{
var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
binaryFormatter.Serialize(memoryStream, obj);
return memoryStream.ToArray();
}
}
Upvotes: 2