是P / Invoke的[输入,输出]封送数组属性可选? [英] Are P/Invoke [In, Out] attributes optional for marshaling arrays?

查看:125
本文介绍了是P / Invoke的[输入,输出]封送数组属性可选?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设有一个纯C接口类似以下,从本机DLL导出原生功能:

Assume that there is a native function with a pure-C interface like the following one, exported from a native DLL:

// NativeDll.cpp

extern "C" void __stdcall FillArray(
    int fillValue, 
    int count, 
    int* data)
{
    // Assume parameters are OK...

    // Fill the array
    for (int i = 0; i < count; i++)
    {
        data[i] = fillValue;
    }
}

以下的P / Invoke工作正常(与VS2010 SP1测试):

The following P/Invoke works fine (tested with VS2010 SP1):

[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)]
public static extern void FillArray(
    int fillValue,
    int count,
    [In, Out] int[] data
);

以及本的P / Invoke,与上面相同,但是的没有的在 [输入,输出] 属性

as well as this P/Invoke, same as above, but without the [In, Out] attributes:

[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)]
public static extern void FillArray(
    int fillValue,
    int count,
    int[] data
);

所以,那些 [输入,输出] 属性的可选作为编组数组?
什么是他们的目的,如果有的话?
是否确定忽略他们在我们的P / Invoke声明?

So, are those [In, Out] attributes optional for marshaling arrays? What is their purpose, if any? Is it OK to omit them in our P/Invoke declarations?

推荐答案

没有,他们没有的究竟的可选的。碰巧偶然的工作。但它是一种非常常见的事故。它的工作原理,因为数组实际上并没有被封。该PInvoke的编组看到,在C#阵列已兼容与本地阵列可以跳过步骤来创建它的一个副本。它只是引脚排列并传递指向本地code。

No, they are not exactly optional. It just happens to work by accident. It is however a very common accident. It works because the array doesn't actually gets marshaled. The pinvoke marshaller sees that the C# array is already compatible with the native array so skips the step to create a copy of it. It merely pins the array and passes the pointer to the native code.

这当然是非常有效的,你将不可避免地得到结果回来,因为本机code是直接写数组元素。所以,无论是[IN]还是[OUT]事属性。

This is of course very efficient and you will inevitably get the results back because the native code is directly writing the array elements. So neither the [In] nor the [Out] attributes matter.

它得到如果数组元素类型并非如此简单很多迷雾。这不是那么容易辨认这不是blittable或布局不匹配编组打完一个结构或类类型的元素类型的PInvoke编组的的使数组的副本。尤其是布局不兼容可非常难以确定,因为管理布局是无法发现。并且可以根据所使用的抖动变化。它可以在x86的工作,但不是x64时,例如,pretty讨厌当选择值为anycpu。得到它的修改后的副本复制回C#阵列的确实需要[OUT]。

It gets much murkier if the array element type isn't that simple. It isn't that easy to identify an element type that's a struct or class type that isn't blittable or whose layout doesn't match after marshaling so the pinvoke marshaller has to make a copy of the array. Especially the layout incompatibility can be very hard to identify because the managed layout is undiscoverable. And can change depending on the jitter that is used. It may work in x86 but not x64 for example, pretty nasty when AnyCPU is selected. Getting it to copy the modified copy back to the C# array does require [Out].

不知道该怎么劝,比其他任何人曾经得到的是其声明中明确解雇。也许你应该永远是明确的,当数组元素类型,所以你永远不会有一个意外并不简单。

Not sure what to advice, other than that nobody ever got fired for being explicit in their declarations. Perhaps you should always be explicit when the array element type isn't simple so you'll never have an accident.

这篇关于是P / Invoke的[输入,输出]封送数组属性可选?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆