Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you Marshal a byte array in C#?

I'm trying to call the following C++ function that's wrapped up into a DLL:

unsigned char * rectifyImage(unsigned char *pimg, int rows, int cols)

My import statement looks like the following:

[DllImport("mex_rectify_image.dll")]
unsafe public static extern IntPtr rectifyImage(
byte[] data, int rows, int columns);

And my call routine looks like the following:

byte[] imageData = new byte[img.Height * img.Width * 3];
// ... populate imageData
IntPtr rectifiedImagePtr = rectifyImage(imageData, img.Height, img.Width);
Byte[] rectifiedImage = new Byte[img.Width * img.Height * 3];
Marshal.Copy(rectifiedImagePtr, rectifiedImage, 0, 3 * img.Width * img.Height);

However, I keep getting a runtime error:

A first chance exception of type System.AccessViolationException occurred in xxx.dll Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

I'm just wondering if the fault lies in the way I'm marshaling my data or in my imported DLL file... anyone have any ideas?

like image 976
Tim Avatar asked Aug 06 '10 18:08

Tim


People also ask

What is a unmanaged array in C++?

Unmanaged arrays are either COM-style safe arrays or C-style arrays with fixed or variable length. Safe arrays are self-describing arrays that carry the type, rank, and bounds of the associated array data. C-style arrays are one-dimensional typed arrays with a fixed lower bound of 0.

How do you find the lower bound of a safe array?

The SAFEARRAY element type is captured from the type library and saved in the SAFEARRAY value of the UnmanagedType enumeration. Because the rank and bounds of the safe array cannot be determined from the type library, the rank is assumed to equal 1 and the lower bound is assumed to equal 0.

How to pass an array as an in/out parameter?

In an application consisting entirely of managed code, the common language runtime passes array types as In/Out parameters. In contrast, the interop marshaller passes an array as In parameters by default. With pinning optimization, a blittable array can appear to operate as an In/Out parameter when interacting with objects in the same apartment.

Can a blittable array be used as an in/out parameter?

With pinning optimization, a blittable array can appear to operate as an In/Out parameter when interacting with objects in the same apartment.


1 Answers

This is likely occurring because the calling convention of the method is not as the marshaller is guessing it to be. You can specify the convention in the DllImport attribute.

You don't need the 'unsafe' keyword in the C# declaration here as it's not 'unsafe' code. Perhaps you were trying it with a 'fixed' pointer at one point and forgot to remove the unsafe keyword before posting?

like image 142
Tergiver Avatar answered Sep 20 '22 02:09

Tergiver