我想将对 C# 对象的引用放入非托管内存 (C) 中,我猜是作为指针 (int),当 C 代码稍后回调到 C# 时,我想从非托管内存,因此我可以解析它并访问该对象。原因是 C 代码控制应该使用哪个对象,没有真正的替代方案。我对 C 代码的控制有限,并且 C++/CLI 不是一个选项。
问题:这可能并且安全吗?如果可以,如何实现?
最佳答案
嗯,这是可能的。主要担心的是您的方案与垃圾收集器非常不兼容,它在压缩堆时移动内存中的对象。这是你可以阻止的事情,你可以固定该对象,这样 GC 就无法移动它。您使用 GCHandle.Alloc() 分配 GCHandleType.Pinned 句柄,并将 GCHandle.AddrOfPinnedObject() 的返回值传递给您的 C 代码,大概是通过 pinvoke 调用。
您必须担心该对象需要保持固定多长时间。最多几秒钟就可以了,但如果长时间保持固定状态,就会对 GC 造成相当大的损害。这是 GC 必须不断绕过的一 block 石头。而且堆段永远无法回收,单个对象可能会花费您几兆字节。
在这种情况下,您应该考虑分配非托管内存并将对象复制到其中。使用 Marshal.AllocHGlobal() 进行分配,使用 Marshal.StructureToPtr() 将对象复制到其中。如果您修改对象并且更改也需要对 C 代码可见,则可能会多次。
无论哪种方式,对象都必须blittable,否则会出现运行时错误。这是一个昂贵的词,仅意味着对象必须具有简单的字段类型,C 程序有机会正确读取这种类型。不要使用bool。请小心 C 程序中的声明,如果错误,很容易损坏堆。
关于c# - 在非托管内存中保存对托管对象的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32295586/