My C# application interacts with the C application via the "callbacks" mechanism.
On the C side I have Point
struct:
struct Point {
float x, y, z;
};
To transfer points from C to C# I pass my C# delegate callback function pointsCallback
to C function getPoints
.
typedef void(*PointsCallback)(const Point* points, int size);
void getPoints(PointsCallback callback);
delegate void PointsCallback(IntPtr points, int size);
[DllImport(...)]
static extern void getPoints(PointsCallback callback);
My PointsCallback
C# implementation looks like this:
[StructLayout(LayoutKind.Sequential)]
struct Point {
public float x, y, z;
}
// called from c code
void PointsCallbackImpl(IntPtr points, int size) {
var pointSize = Marshal.SizeOf<Point>();
var myPoints = new List<Point>();
for (int i = 0; i < size; ++i) {
myPoints.Add(Marshal.PtrToStructure<Point>(points + i * pointSize));
}
// do something with myPoints
}
The problem is this code is quite slow compared to python's np.array
which allows me to save all points
as a binary array and interpret them via np.dtype
.
Is there any C# analog to np.array
behavior, which allows to store everything in binary form and only interpret data as some structs?
I am not sure what 'slow' means in this context, but the example below takes 0.3285 milliseconds, or 328500 nanoseconds to convert 1000 points.
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static unsafe extern void memcpy(void* dst, void* src, int count);
[StructLayout(LayoutKind.Sequential)]
struct Point
{
public float x, y, z;
}
static unsafe void PointCallback(IntPtr ptPoints, int size)
{
Point[] points = new Point[size];
fixed (void* pDest = &points[0]) {
memcpy(pDest, (void*)ptPoints, Marshal.SizeOf<Point>() * size);
}
}
And here is my test:
Point[] points = new Point[1000];
for (int i=0; i<1000; i++) {
points[i] = new Point() { x= i, y = i,z = i };
}
var ptPoints = GCHandle.Alloc(points, GCHandleType.Pinned);
PointCallback(ptPoints.AddrOfPinnedObject(), 1000);
ptPoints.Free();