C # for unmanaged dll interop data structures
I have an unmanaged DLL that provides a function that takes a pointer to a data structure. I have C # code that creates a data structure and calls a dll function without any problem. At the point of calling the function in the dll, the pointer is correct.
My problem is that the DLL stores the pointer to the structure and uses the data structure pointer at a later point in time. When the DLL comes around to using a pointer, it is invalidated (I'm guessing the .net runtime moved the memory somewhere else).
What are the possible solutions to this problem?
Possible solutions I can think of are the following:
- How can I fix the memory location of the data structure? I don't know how to do this in C # or even if you can.
- Allocate memory manually so I can control it for example. using Marshal.AllocHGlobal
- Change the contract of the DLL function to copy the struct data (this is what I am currently doing as a short term change, but I don't want to change the DLL at all if I can help, as this is not my code to start with).
Are there any other better solutions?
a source to share
You can allocate the struct using AllocHGlobal , which puts it in unmanaged memory where the GC won't move or release it, you can also use a helper class like this to have HZ pin memory so it won't move or release until it is secured.
a source to share
- Allocate memory manually so I can control it for example. using Marshal.AllocHGlobal
Close enough.
In this particular case, I would P / Invoke LocalAlloc allocate a block of memory and use StructureToPtr to initialize it.
UPDATE: Since you can edit the DLL, I would change the DLL to provide AllocXXX and FreeXXX functions.
a source to share
The GCHandle class was designed to handle this exact scenario. Essentially, you put a copy of your structure on the heap and then call GCHandle.Alloc
with GCHandleType.Pinned
. When the DLL is executed with the structure, call GCHandle.Free
. To provide the DLL function with the address of the object, pass it GCHandle.AddrOfPinnedObject
. As long as it is pinned, the GC will not move it.
a source to share