Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 固定.NET对象数组_C#_.net_Mono_Garbage Collection_Interop - Fatal编程技术网

C# 固定.NET对象数组

C# 固定.NET对象数组,c#,.net,mono,garbage-collection,interop,C#,.net,Mono,Garbage Collection,Interop,我想固定一个.NET对象数组(包括对象),以便允许本机函数对对象进行一些处理。据我所知,GCHandle.Alloc()不允许我这样做,因为这样的数组包含不可Blitttable的引用(对象也可能包含引用) 有没有其他办法来实现这一点?我可以接受非常粗俗的建议或需要Mono的建议。在.NET中的数组是在连续内存中表示的。这意味着在内存中,在元素0之后,元素1将直接位于前一个元素之后,依此类推 如果使用固定数组,则意味着整个元素列表也固定在内存中,并且可以在非托管代码中处理 但是,正如您所提到的,

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


有没有其他办法来实现这一点?我可以接受非常粗俗的建议或需要Mono的建议。

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

如果使用固定数组,则意味着整个元素列表也固定在内存中,并且可以在非托管代码中处理

但是,正如您所提到的,只有当类型是可blittable类型时才有意义(从技术上讲,这是不正确的,如果类型能够封送到非托管代码,尽管在可blittable主类型和p/Invoke/COM互操作层自动处理的内容之间有很多重叠)

因此,如果您有一个值类型数组,您可以调用
GCHandle.Alloc
,它将为您锁定该数组。但是,P/Invoke层已经为您完成了这项工作,因此您不应该对此感到担心

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

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


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

您可以查看
Marshal.AllocHGlobal
Marshal.WriteIntPtr
。这是框架提供的处理非托管内存的官方方式。不过,我不确定这是否有帮助

编辑


另请参见

即使可以固定这些对象,您希望对其执行什么操作?引用不一定是指针;你将无法从本地访问它们。这如何回答这个问题?@casperOne-我的想象告诉我,如果他想完成他在问题中提出的要求,唯一的方法是他将所有数组封送到非托管块中。P/Invoke或COM互操作层会自动为您执行此操作。@casperOne-听起来好像是op想自己执行此操作。这可能是不必要的,但是如果他的意图是稍后调用某些汇编代码来处理数组,并且他不能使用P/Invoke,那么他很可能无法首先调用汇编代码,而不首先将数组转换为C/C++公开的本机代码。@casperOne-我指的是一个充满引用的数组。在我看来,固定数组和数组引用的每个对象是有意义的。C代码只需知道它正在处理一个C#数组和C#对象,并通过模仿CLR默认内存布局的指针算法访问其字段。如果得到一个充满引用的数组,请锁定该数组并锁定数组中的所有引用,您仍然需要处理我在第五段中提到的问题:您不知道本机代码中的类型系统是什么,所以这些指针对您来说毫无意义。如果你已经使用了C++/CLI来混合代码(.NET和C++代码),那么你就应该公开一个C++类开始使用.NET类型,因为你没有得到任何好处。到目前为止,我还没有成功地用引用来排列数组(对于引用类型成员来说,对象也是一样),这是可能的吗?关于你的第五段:一旦我找到了钉住问题的解决方案,这将是下一个挑战-分析.NET内存布局,编写C函数,将类型转换为C中有用的内容@user1622959这是答案的全部要点,你不应该这样做,您应该跨托管/非托管边界封送数据。答案是“不,不要这样做,使用封送处理”。为什么要读取CLR类型?你要解决的真正问题是什么,我保证不是这样。想象一下,我有一个非常庞大的对象数组,我想迭代它们,并根据它们在本机代码中的一些成员值执行操作。现在想象一下,这是非常关键的性能,在内存中复制对象的GB不是一个选项。然后剩下的唯一一件事就是钉住并尝试编写能够处理C#内存布局和类型的C代码。