Passing large Vector array to native plugin without copying

Hey, I’m wondering how I can pass a large array of Vector3s to a C++ plugin without the marshaller copying the data. This is what I’m currently doing.

[DllImport ("NativeLibrary")]
private static extern void PopulateVerts([In, Out] Vector3[] verts);

Vector3[] verts = new Vector3[20000];

System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
 
PopulateVerts(verts);
 
stopwatch.Stop();
Debug.Log("Populate Verts: " + stopwatch.Elapsed);

and on the C++ side I have this

struct Vert
{
    float x,y,z;
};

extern "C" void EXPORT_API PopulateVerts(Vert* verts)
{
        
}

It’s taking 0.002 seconds to send the array to C++ which leads me to believe that the marshaller is copying the data. Is there any way to just pass a pointer to the array and modify the values in C++ without actually copying the data over the managed/unmanaged barrier?

You can pin the object in memory using a GCHandle and then pass the address to the C++ function. See this for allocating a pinned GCHandle.

I have done this by just passing a ref to the first element of the array. So something like:

In C:
void nativeFunc(float* firstElem);

Then in C#:
void nativeFunc(ref float firstElem);

Then to call:
float myFloats = new float[123];
nativeFunc(ref myFloats[0]);

Not sure how kosher this is…and definitely your native code should not save the pointer across calls!