tags:

views:

87

answers:

5

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 e.g. 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?

A: 

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.

Sophtware
Static instances are not guaranteed to stay put in memory. In particular, it's likely they'll get promoted to higher generations and thus get moved.
Dan Bryant
+1  A: 

See the fixed C# statement: http://msdn.microsoft.com/en-us/library/f58wzh21(VS.80).aspx

Daniel Renshaw
So there is a way to mark the memory now to be moved. I also see that it forces you to use the 'unsafe' keyword. Are there any downsides to using the 'unsafe' vis manually manually allocating memory?
Shane Powell
As MSDN says "Using unsafe code introduces security and stability risks" (amoung other implications: http://msdn.microsoft.com/en-us/library/t2yzs44b(v=VS.80).aspx). The answer to your question is, I'm afraid, "it depends". If your application needs to run in lower trust environments (e.g. web server) unsafe is not an option, but then p/invoke won't be allowed either I think. If this is predominantly a managed application, maybe using unsafe and doing more in C# is the way to go. But it probably comes down to whatever you feel most comfortable with.
Daniel Renshaw
+1  A: 
  • Allocate memory manually so that I have control over it e.g. 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.

Joshua
+2  A: 

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.

Dan Bryant
This is what I leaning towards doing, +1 for the link to the helper function. I was thinking of doing extractly what that helper function does.
Shane Powell
A: 

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.

Stephen Cleary