C# · 12月 24, 2021

c# – Marshal的[In] [Out]属性

我在我的C#代码中调用了一个非托管函数.

该功能的声明如下:

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

我使用这个函数如下:

[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);

虽然我提到了byte [] inputBuffer的[InAttribute],但该函数仍然改变了a的值.似乎CLR正在使用其自己的默认编组行为.
我使用了byte []因为它与C#等价于unsigned char *.

当我用char []替换byte []时,CLR将遵循我的In-Out属性.

我非常感谢你的帮助.
有关更多信息,请阅读此msdn page.

解决方法 从 documentation开始,我强调:

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.

由于字节是blittable,因此您的字节数组被固定而不是复制,因此编组为In / Out.

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

C#类型的char是not blittable.不固定char数组,因此[In] char []编组作为In参数.