C#到非托管dll数据结构互操作

时间:2010-05-18 19:17:59

标签: c# .net interop

我有一个非托管DLL,它暴露了一个带有指向数据结构的指针的函数。我有C#代码创建数据结构并调用dll函数没有任何问题。在函数调用dll时,指针是正确的。

我的问题是DLL保留指向结构的指针,并在稍后的时间点使用数据结构指针。当DLL开始使用指针时它变得无效(我假设.net运行时已将内存移到其他地方)。

这个问题的可能解决方案是什么?

我能想到的可能解决方案是:

  • 以某种方式修复数据结构的内存位置?我不知道你会怎么用C#或者你可以这样做。
  • 手动分配内存,以便我可以控制它,例如使用Marshal.AllocHGlobal
  • 更改DLL函数契约以复制结构数据(这是我目前正在做的短期更改,但如果我可以帮助它,我根本不想更改dl​​l,因为它不是我的代码开始)。

还有其他更好的解决方案吗?

5 个答案:

答案 0 :(得分:2)

您可以使用AllocHGlobal分配结构,将其置于非托管内存中,GC不会移动它或释放它。你也可以使用像this这样的辅助类让GC引脚作为内存,所以在取消固定之前它不会被移动或释放。

答案 1 :(得分:1)

答案 2 :(得分:1)

  • 手动分配内存,以便我可以控制它,例如使用Marshal.AllocHGlobal

非常接近。

在这个特定的情况下,我P / Invoke LocalAlloc分配内存块并使用StructureToPtr来初始化它。

更新:由于您可以编辑DLL,我会更改DLL以提供AllocXXX和FreeXXX功能。

答案 3 :(得分:0)

如果没有手头的DLL试试这个,很难说这是否有用。我会尝试在C#类中使对象“固定”,这样内存就会在应用程序的生命周期中挂起。然后只需将静态对象传递给DLL。

答案 4 :(得分:0)

GCHandle类旨在处理这种确切的情况。基本上,您将结构的副本装入堆中,然后使用GCHandle.Alloc调用GCHandleType.Pinned。当DLL完成结构时,请调用GCHandle.Free。要为DLL函数提供对象的地址,请将其传递给GCHandle.AddrOfPinnedObject。只要它被固定,GC就不会移动它。