Search code examples
c#c++interop

Read only shared memory between C#->C++


,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?


Solution

  • 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();