简体   繁体   中英

C# to unmanaged dll data structures interop

I have a unmanaged DLL that exposes a function that takes a pointer to a data structure. I have C# code that creates the data structure and calls the dll function without any problem. At the point of the function call to the dll the pointer is correct.

My problem is that the DLL keeps the pointer to the structure and uses the data structure pointer at a later point in time. When the DLL comes to use the pointer it has become invalid (I assume the .net runtime has moved the memory somewhere else).

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.
  • Allocate memory manually so that I have control over it eg using 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).

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. 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.

  • Allocate memory manually so that I have control over it eg using Marshal.AllocHGlobal

Pretty close.

In this specific case I'd P/Invoke LocalAlloc to allocate the memory block and use StructureToPtr to initialize it.

UPDATE: Since you can edit the DLL I'd change the DLL to provide AllocXXX and FreeXXX functions.

Without having the DLL on hand to try this, it's hard to say if this would work. I would try making the object "fixed" in your C# class, that way the memory hangs out for the life of you application. Then just pass the static object to the DLL.

The GCHandle class was designed to handle this exact scenario. Essentially, you box a copy of your struct onto the heap, and then call GCHandle.Alloc with GCHandleType.Pinned . When the DLL is done with the structure, call GCHandle.Free . To give the DLL function the address of the object, pass it GCHandle.AddrOfPinnedObject . As long as it is pinned, the GC won't move it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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