6

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

有没有其他选择可以实现这一目标?我会接受非常 hack-y 的建议或需要 Mono 的建议。

4

2 回答 2

10

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

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

但是,正如您所提到的,只有当类型是 blittable 类型时才有意义(从技术上讲,这是不正确的,如果该类型能够被编组为非托管代码,尽管 blittable 之间有很多重叠P/Invoke/COM Interop 层自动处理的主要类型和内容)。

所以如果你有一个值类型的数组,你可以调用GCHandle.Alloc它,它会为你固定数组。但是,P/Invoke 层已经为您完成了这项工作,因此您不必担心这一点。

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

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

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

于 2012-11-08T16:31:50.990 回答
0

你可以看看Marshal.AllocHGlobalMarshal.WriteIntPtr。这是框架提供的使用非托管内存的官方方式。不确定它是否会有所帮助。

编辑

另请参阅https://stackoverflow.com/a/878147/301525

于 2012-11-08T16:37:26.087 回答