固定.NET对象数组

时间:2012-11-08 16:22:00

标签: c# .net mono garbage-collection interop

我想固定.NET对象(包括对象)的数组,以便允许本机函数对对象进行一些处理。据我所知,GCHandle.Alloc()不允许我这样做,因为这样的数组包含引用(并且对象也可能包含引用),这些引用不是blittable。

还有其他选择吗?对于非常黑客的建议或需要Mono的建议我会没事的。

2 个答案:

答案 0 :(得分:9)

.NET中的数组表示在连续的内存中。所以这意味着在内存中,在元素0之后,元素1将在前一个元素后直接,依此类推。

如果您使用GCHandle.Alloc固定数组,那么这意味着整个元素列表也会固定在内存中,您可以在非托管代码中处理它。

然而,正如你所提到的,只有类型是blittable类型才有意义(从技术上讲,这不是真的,如果类型能够被编组为非托管代码,尽管这里有很多重叠在blittable主要类型和P / Invoke / COM Interop层自动处理的东西之间。

因此,如果您有一个值类型数组,则可以调用GCHandle.Alloc并为您固定数组。但是,P / Invoke层已经为你做了这个,所以你不应该关心这个。

如果你的数组中有很多引用,那么将它编组为unamanged代码无论如何都没有意义;即使您固定每个引用,非托管代码也不会知道如何处理内存中的引用,因为类型系统不支持引用在内存中指向的.NET类型。

如果.NET中的类实际上是本机结构的包装/ .NET表示,那么最好在.NET中创建该结构的数组,将所有数据复制到其中,然后将其发送到你的原生代码。

或者,您可以使用C ++ / cli编写类,以便于在本机代码中访问.NET成员。

答案 1 :(得分:0)

您可以查看Marshal.AllocHGlobalMarshal.WriteIntPtr。这是框架提供的处理非托管内存的官方方式。不确定它是否有用。

修改

另见https://stackoverflow.com/a/878147/301525