I have an application in C# that needs to share some binary data with Python, and I'm planning to use shared memory (memory mapped file). Thus, I need to have the same binary structure on both sides.
I create a struct in C# (ST_Layer) that has an array of items of another struct (ST_Point). To access those items I have defined a function getPoint that will return a pointer to the position of the requested ST_Point.
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
class TestProgram
{
[StructLayout(LayoutKind.Explicit, Pack = 8)]
public struct ST_Point
{
[FieldOffset(0)] public double X;
[FieldOffset(8)] public double Y;
}
[StructLayout(LayoutKind.Explicit, Pack = 8)]
public unsafe struct ST_Layer
{
[FieldOffset(0)] public ushort nPoints;
[FieldOffset(8)] public double fHeight;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
[FieldOffset(16)] public ST_Point[] Points;
public unsafe ST_Point* getPoint(int n)
{
fixed (ST_Layer* thisPtr = &this)
{
int ptr = (int)&(thisPtr->Points) + n * ((16 + 3) / 4) * 4; // Sizeof ST_Point 16
return (ST_Point*)ptr;
}
}
}
static void Main(string[] args)
{
unsafe
{
ST_Layer layer = new ST_Layer();
layer.nPoints = 3;
layer.fHeight = 4;
layer.getPoint(0)->X = 5;
layer.getPoint(3)->Y = 6;
for (int i = 0; i < 10; i++)
Debug.WriteLine("Data [" + i + "] " + layer.getPoint(i)->X + ", " + layer.getPoint(i)->Y + " - ");
while (true)
Thread.Sleep(50);
}
}
}
I have 2 questions:
- The previous code works if I compile the code for x86, but not for x64 or 'Any CPU' ('System.AccessViolationException' exception in 'layer.getPoint(0)->X'). Is it an expected behaviour? What can I do to solve this exception?
- I'm using the
getPointfunction to access theST_Pointarray because I have not seen a better way of accessing it. Is it possible to access it as a normal array (i.e.layer.Points[0].X)? I can't create the array ofST_Point(layer.Points = new ST_Point[10]), as it'll be created outside theST_Layer, and data will not be passed to Python.
I've seen this and this, but don't know how to access the individual fields of ST_Point.
Thank you for your help.
[Also, thank you R. Martinho Fernandes for your hint regarding the x86/x64 issue]
If you are using a recent version of .NET you can use
System.Runtime.CompilerServices.InlineArrayto read and write the struct directly from and to the MMF, without any unsafe code.The
InlineArrayattribute allows you to specify a struct which contains a fixed number of elements of a specific value type, which can be accessed via an indexing operation: