A linked list of structures can be passed back, but it would be rather difficult with it, since you would have to write code to scroll through pointers, read and copy data from the built-in memory to a managed memory space. Instead, I would recommend a simple array of structures.
If you have a C structure like the following (assuming 32 bit ints) ...
struct Point { int x; int y; int z; }
... then you would imagine it almost the same as in C #:
[StructLayout(LayoutKind.Sequential] struct Point { public int x; public int y; public int z; }
Now, to pass the array back, it would be easier if your own code allocated the array and passed it as a pointer along with another pointer that defines the size in the elements.
Your C prototype might look like this:
The P / Invoke declaration will be as follows:
[DllImport("YourLib.dll")] static extern int GetPoints( [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out Point[] array, out int arraySizeInElements);
The MarshalAs
attribute indicates that the array should be marshaled using the size specified in the second parameter (you can learn more about this in MSDN, "Default Marshaling for Arrays" ).
If you use this approach, please note that you should use CoTaskMemAlloc
to allocate your own buffer, as this is what the .NET marshaler expects, otherwise you will get memory leaks and / or other errors in your application.
Here is a snippet from a simple example that I compiled while checking my answer:
struct Point { int x; int y; int z; }; extern "C" int GetPoints(Point ** array, int * arraySizeInElements) {
A managed caller can process data very simply (in this example, I put all the interaction code in a static class called NativeMethods
):
NativeMethods.Point[] points; int size; int result = NativeMethods.GetPoints(out points, out size); if (result == 0) { Console.WriteLine("{0} points returned.", size); foreach (NativeMethods.Point point in points) { Console.WriteLine("({0}, {1}, {2})", point.x, point.y, point.z); } }