Yasser Mohseni
Yasser Mohseni

Reputation: 463

Marshal's [In] [Out] Attributes

I'm invoking an unmanaged function in my C# code.

The declaration of this function is as follow:

int myFun(unsigned char* inputBuffer, unsigned char* &outputBuffer);

I use this function as follow:

[DllImport("myDLL.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int myFun([In] byte[] inputBuffer, out IntPtr outputBuffer);

byte[] a = Encoding.ASCII.GetBytes("sampletext!");
IntPtr b;
res = myFun(a, out b);

Although I mentioned [InAttribute] for byte[] inputBuffer, the function still changeds the values of a. It seems that CLR is using its own default marshaling behavior. I used byte[] because it is C# equivalent for unsigned char*.

When I substitite byte[] with char[] the CLR will follow my In-Out attributes.

I highly appreciate your help. For more information please read this msdn page.

Upvotes: 9

Views: 5710

Answers (1)

David Heffernan
David Heffernan

Reputation: 613302

From the documentation, with my emphasis:

As an optimization, arrays of blittable types and classes that contain only blittable members are pinned instead of copied during marshaling. These types can appear to be marshaled as In/Out parameters when the caller and callee are in the same apartment. However, these types are actually marshaled as In parameters, and you must apply the InAttribute and OutAttribute attributes if you want to marshal the argument as an In/Out parameter.

Since byte is blittable, your array of byte is pinned rather than copied, and so marshals as In/Out.

When I substitute byte[] with char[] the CLR will follow my In-Out attributes.

The C# type char is not blittable. An array of char is not pinned, and so [In] char[] marshals as an In parameter.

Upvotes: 14

Related Questions