简体   繁体   English

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

[英]C# to unmanaged dll data structures interop

I have a unmanaged DLL that exposes a function that takes a pointer to a data structure. 我有一个非托管的DLL,它公开了一个需要指向数据结构的指针的函数。 I have C# code that creates the data structure and calls the dll function without any problem. 我有C#代码,可以创建数据结构并调用dll函数,而不会出现任何问题。 At the point of the function call to the dll the pointer is correct. 在对dll的函数调用时,指针是正确的。

My problem is that the DLL keeps the pointer to the structure and uses the data structure pointer at a later point in time. 我的问题是DLL保留了指向结构的指针,并在以后的某个时间点使用了数据结构指针。 When the DLL comes to use the pointer it has become invalid (I assume the .net runtime has moved the memory somewhere else). 当DLL开始使用指针时,它已变得无效(我假设.net运行时已将内存移至其他位置)。

What are the possible solutions to this problem? 该问题有哪些可能的解决方案?

The possible solutions I can think of are: 我能想到的可能解决方案是:

  • Fix the memory location of the data structure somehow? 固定数据结构的内存位置吗? I don't know how you would do this in C# or even if you can. 我不知道您将如何使用C#或什至可以做到这一点。
  • Allocate memory manually so that I have control over it eg using Marshal.AllocHGlobal 手动分配内存,以便我可以控制它,例如使用Marshal.AllocHGlobal
  • Change the DLL function contract to copy the structure data (this is what I'm currently doing as a short term change, but I don't want to change the dll at all if I can help it as it's not my code to begin with). 更改DLL功能协定以复制结构数据(这是我目前作为短期更改所做的事情,但是如果我能帮助的话,我根本不想更改dl​​l,因为这不是我的代码开头)。

Are there any other better solutions? 还有其他更好的解决方案吗?

You can allocate the structure using AllocHGlobal , which puts it in unmanaged memory, where the GC won't move it around or release it. 您可以使用AllocHGlobal分配结构,将其放入非托管内存中,GC不会在其中移动或释放它。 You could also use a helper class like this to have the GC pin the memory, so it won't be moved or released until un-pinned. 你也可以使用一个辅助类像这样有GC引脚的内存,所以它不会被移动或释放,直到取消固定。

  • Allocate memory manually so that I have control over it eg using Marshal.AllocHGlobal 手动分配内存,以便我可以控制它,例如使用Marshal.AllocHGlobal

Pretty close. 八九不离十。

In this specific case I'd P/Invoke LocalAlloc to allocate the memory block and use StructureToPtr to initialize it. 在这种情况下,我会P /调用LocalAlloc来分配内存块,并使用StructureToPtr对其进行初始化。

UPDATE: Since you can edit the DLL I'd change the DLL to provide AllocXXX and FreeXXX functions. 更新:因为您可以编辑DLL,所以我将更改DLL以提供AllocXXX和FreeXXX函数。

Without having the DLL on hand to try this, it's hard to say if this would work. 如果没有手头的DLL来尝试此操作,很难说这是否可行。 I would try making the object "fixed" in your C# class, that way the memory hangs out for the life of you application. 我会尝试将对象“固定”在您的C#类中,这样,内存就可以在您的应用程序生命周期中闲逛。 Then just pass the static object to the DLL. 然后只需将静态对象传递给DLL。

The GCHandle class was designed to handle this exact scenario. GCHandle类旨在处理这种确切的情况。 Essentially, you box a copy of your struct onto the heap, and then call GCHandle.Alloc with GCHandleType.Pinned . 从本质上讲,你打你的结构复制到堆上,然后调用GCHandle.AllocGCHandleType.Pinned When the DLL is done with the structure, call GCHandle.Free . 当DLL完成结构后,调用GCHandle.Free To give the DLL function the address of the object, pass it GCHandle.AddrOfPinnedObject . 要为DLL函数提供对象的地址,请将其传递给GCHandle.AddrOfPinnedObject As long as it is pinned, the GC won't move it. 只要将其固定,GC就不会移动它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM