Marshalling structure containing int and int [] from C # to C ++

I have a C ++ DLL with unmanaged code and C # UI. There is a function imported from the C ++ DLL that takes a write-by-me structure as a parameter.

After sorting the structure (MyImage) I wrote from C # to C ++, I can access the contents of the int [] array inside it, but the contents are different. I don’t know what I’m missing here, because I spent a lot of time and tried several tricks to solve this problem (obviously not enough).

MyImage structure in C #:

[StructLayout(LayoutKind.Sequential)] struct MyImage { public int width; public int height; public int[] bits; //these represent colors of image - 4 bytes for each pixel } 

MyImage structure in C ++:

 struct MyImage { int width; int height; Color* bits; //typedef unsigned int Color; MyImage(int w, int h) { bits = new Color[w*h]; } Color GetPixel(int x, int y) { if (x or y out of image bounds) return UNDEFINED_COLOR; return bits[y*width+x]; } } 

Declaring a C # function with the MyImage parameter as:

 [DLLImport("G_DLL.dll")] public static extern void DisplayImageInPolygon(Point[] p, int n, MyImage texture, int tex_x0, int tex_y0); 

C ++ implementation

 DLLEXPORT void __stdcall DisplayImageInPolygon(Point *p, int n, MyImage img, int imgx0, int imgy0) { //And below they have improper values (i don't know where they come from) Color test1 = img.GetPixel(0,0); Color test2 = img.GetPixel(1,0); } 

Therefore, when debugging the problem, I noticed that the array MyImage.bits in the C ++ structure contains different data.

How can i fix this?

+4
source share
3 answers

Since the bits field is a pointer to memory allocated in native code, you need to declare it as IntPtr in C # code.

 struct MyImage { public int width; public int height; public IntPtr bits; } 

If you want to access individual pixels in C # code, you need to write the GetPixel method, as in C ++ code.

Note that since the bits field is a pointer to memory allocated in native code, I expect the actual code to have a destructor for the structure that calls delete[] bits . Otherwise, your code will leak.

It also means that you will need to create and destroy instances in your own code and never do it in managed code. Is this the policy you are currently following? I suspect it is not based on the code that I see here.

You also need to reconsider passing struct by value. Do you really want to take a copy of it when you call this function? This means that you have two instances of the structure whose bits fields point to the same memory. But who owns this memory? This structure really needs to be passed by reference.

I think you have some problems in your design, but I don’t see enough code or know enough about your problem to give you specific advice.


In the comments, you state that your main goal is to port these bits from your C # code to C ++ code. I suggest you do it as follows:

 MyImage* NewImage(int w, int h, Color* bits) { MyImage* img = new MyImage; img->w = w; img->h = h; img->bits = new Color[w*h]; for (int i=0; i<w*h; i++) img->bits[i] = bits[i]; return img; } void DeleteImage(MyImage* img) { delete[] img->bits; delete img; } void DoSomethingWithImage(MyImage* img) { // do whatever it is you need to do } 

On the C # side, you can declare it as follows:

 [DllImport(@"dllname.dll", CallingConvention=CallingConvention.Cdecl)] static extern IntPtr NewImage(int w, int h, int[] bits); [DllImport(@"dllname.dll", CallingConvention=CallingConvention.Cdecl)] static extern void DeleteImage(ImtPtr img); [DllImport(@"dllname.dll", CallingConvention=CallingConvention.Cdecl)] static extern void DoSomethingWithImage(ImtPtr img); 
+4
source

The first thing you should try is to declare your C # code with unsigned int types. Perhaps one bit is interpreted as a sign for your int.

So in C # something like this (just note that the bit is now uint[] ):

 [StructLayout(LayoutKind.Sequential)] struct MyImage { public int width; public int height; public uint[] bits; //these represent colors of image - 4 bytes for each pixel } 
-1
source

You can use the PInvoke Interop Assistant . You simply insert a declaration of structure and function and generate C # code for it. It has helped me many times.

-1
source

Source: https://habr.com/ru/post/1447624/


All Articles