15

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;
};

1 Answer 1

23

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Cool man, thanks a lot. Also, as a quick question, is it possible to Marshal a vector, so that I could just have OuterStruct have a vector of InnerStructs? I know you can't marshal classes, but I thought that perhaps someone had written something tricky to do this.
Not that I know of, but I've never looked. :-)
You cast the pointer to int? What if it is running in a 64-bit process?! You don't need the casts
Please note that's really extremely bad idea to cast IntPtr to int in a case such that. Please don't!
@doug65536 Yes, oops! Fixed! (8 years later)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.