Garbage Collector and P/Invoke

  • Thread starter Thread starter Cory Nelson
  • Start date Start date
C

Cory Nelson

I an P/Invoking a C library. I pass a new delegate in, and the C lib
stores it for later access.

Most of the time I'm able to use it once then I get a null reference
exception, so I'm thinking .NET is collecting. Any way to make it say
until the containing class is destroyed?
 
Cory,

You have one or two choices here. The first is to store a reference to
the delegate somewhere, so that it doesn't get GCed. The other option is to
use the GCHandle structure, and then store that somewhere, which will ensure
that the object doesn't get released until you call Free on it.

Hope this helps.
 
Hmm.. the docs on GCHandle at MSDN aren't that helpful, I'm not 100% on
how to use it.

"System.ArgumentException: Object contains non-primitive or
non-blittable data."

Here's what my code looks like, can you see what's wrong?

public ReportFilter filter;
private GCHandle filterhandle;

....

filter=new ReportFilter(FilterMethod)
filterhandle=GCHandle.Alloc(filter, GCHandleType.Pinned); // exception
here.

....

filterhandle.Free()
 
Cory,

You don't want to pin it. Just pass the filter, don't pass the second
parameter.
 
If I dont pin it, wont the GC be able to move it? (thus invalidating
the func pointer in the C library)
 
Cory,

I've been searching, and as of now, I don't think that it is possible.
Somehow (I'm not sure how) the marshalling infrastructure knows how to pin
the address of the object, and releases it when a call is complete across
the managed/unmanaged boundary.

In .NET 2.0, you can get a function pointer for a delegate, but I don't
know if that keeps a thunk in memory, or just converts the current value.

I thought about using unsafe code, and the fixed statement to pin the
pointer, but you can't get the pointer for a reference type.
 
Found out how!

Make sure your C functions are using stdcall, then use GC.KeepAlive()
on the delegate.
 
Back
Top