,I have C# code that creates 3D geometry and sends it to a C++ library to be rendered. At the moment the data is passed over interop like so (I've reduced the number of arrays passed):
void LoadMeshData(Mesh meshData)
{
var verticesArraySize = meshData.Vertices.Length;
unsafe
{
fixed (float* vertices = meshData.Vertices)
{
Interop.Data.MeshDataObject meshDataObject;
meshDataObject.vertexArraySize = verticesArraySize;
meshDataObject.vertexData = new IntPtr(vertices);
SceneInterop.AddMeshData(meshDataObject);
}
}
Interop.Data.MeshDataObject
is a POD struct that matches a similar struct on the C++ side.
The fixed
obviously goes out of scope after this call, so at the moment I'm copying the array into a structure in C++. This is clearly a huge waste of memory, so ideally I'd like a way to mark the C# memory as permanently "fixed" - is this feasible?
I only ever need to read the data in the C++ library, and I do need to keep it available on the C# side.
Any other suggestions on how I can save myself the copying?
I'm answering my own question here but it is really just the first comment above, @shingo please feel free to put it in as an answer and I'll remove this one.
You can use GCHandle to create a pinned handle, but it will undermine the efficiency of the GC. You may ask the C++ code to allocate the memory and return the pointer to C#
I used verticesHandle = GCHandle.Alloc(vertices, GCHandleType.Pinned)
which lets me share memory nicely.
Later when I'm happy to allow removal of the memory I use
if (verticesHandle.IsAllocated)
verticesHandle.Free();