Search code examples
c#.netinteroppinvokemarshalling

How to marshal a variable sized array of structs? C# and C++ interop help


I have the following C++ structs

struct InnerStruct
{
   int A;
   int B;
};

struct OuterStruct
{
   int numberStructs;
   InnerStruct* innerStructs;
};

And a C++ function

OuterStruct getStructs();

How can I marshal this to C#? Where the C# definitions is

struct OuterStruct {
   InnerStruct[] innerStructs;
};

Solution

  • You'll have to do this manually, since there's no way to tell the P/Invoke layer how much data to marshal from your C++ return value.

    struct OuterStruct {
       int numberStructs;
       IntPtr innerStructs;
    };
    
    OuterStruct s = getStructs(); // using DllImport
    var structSize = Marshal.SizeOf(typeof(InnerStruct));
    var innerStructs = new List<InnerStruct>();
    var ptr = s.innerStructs;
    
    for (int i = 0; i < s.numberStructs; i++)
    {
        innerStructs.Add((InnerStruct)Marshal.PtrToStructure(ptr, 
            typeof(InnerStruct));
        ptr = ptr + structSize;
    }
    

    Note that if you want to free the memory for innerStructs from your C# code, you have to use the standard allocator CoTaskMemAlloc in your C++ code--then you can call Marshal.CoTaskMemFree to free innerStructs.