I know this subject was discussed many times here, but I couldn’t find the answer for my specific situation.
I need to call in C# an unmanaged C method which takes a pointer on a struct object (I don’t speak C fluently :
int doStuff(MYGRID* grid, int x);
But the struct itself references an other struct object :
struct MYGRID {
int hgap;
int vgap;
MYIMAGE* image;
}
struct MYIMAGE {
int res;
int width;
int height;
}
And I also need to set directly the image pointer like this :
MYGRID* pGrid = new MYGRID;
MYIMAGE* pImage = new MYIMAGE;
pGrid->image = pImage;
So, my question is : in C# code, should I use a “struct” object and passing it by “ref” like the P/Invoke Interop Assistant suggests me ? Which means the following code :
MyGrid myGrid = new MyGrid();
MyImage myImage = new MyImage();
myGrid.image = Marshal.AllocHGlobal(Marshal.SizeOf(image)); // A IntPtr in my struct
myGrid.image = Marshal.StructureToPtr(image, myGrid.image, false);
doStuff(ref myGrid, 0);
Or could I use “class” instead of “struct” in order to have the very simple following code :
MyGrid myGrid = new MyGrid();
MyImage myImage = new MyImage();
myGrid.image = myImage;
doStuff(myGrid, 0);
In the first case I use an “IntPtr” in my struct MyGrid, and just a MyImage object in the second case.
Don’t confuse C# struct with C++ struct. They are not the same thing. A C# struct is used to declare a value type. When you aggregate a value type in another type you store it directly in the containing instance instead of storing a reference to an instance stored on the heap. A C++ struct is simply a class where all members by default are public.
In your case, because
MYGRIDcontains a pointer toMYIMAGE, you should useclassas you are doing in you second example. However, therefon themyGridparameter should be removed.Below is some sample code I have tested. The C++ code:
Declaring the C# classes and the external function:
Calling the external function:
If you turn on unmanaged debugging in your C# project you can use the debugger to step into the C++ function and verify that the classes have been correctly marshaled.