I am using a delegate which calls an unmanaged function pointer. This causes the Garbage Collector to collect it before it is used, as described in the CallbackOnCollectedDelegate MDA page on MSDN: MSDN page for CallbackOnCollectedDelegate MDA.
The resolution states that I have to marshal the appropriate delegate as an unmanaged function pointer. My initial reflex was to use:
[MarshalAs(UnmanagedType.FunctionPtr)]
public delegate void EntityCallback([MarshalAs(UnmanagedType.SysInt)] IntPtr entity);
However, the C# compiler won't let me marshal a delegate, even if this is the suggested resolution by MSDN. Moreover, the MSDN page only shows an example of the problem being thrown, but not one of the resolution.
How could I marshal my delegate as an unmanaged function pointer or keep it from being GCed?
EDIT: As suggested, I created a reference of the callback. Therefore, my code changed from/to:
// From:
foo.SetCallback(new EntityCallback(bar));
// To:
call = new EntityCallback(bar); // Referenced in class
foo.SetCallback(call);
Now this does work - but only in Debug mode. When I switch to Release, it crashes at the same point. Why is that?
EDIT 2: More complete code snippet:
public class Test
{
private EntityCallback Call;
private void Bar(System.IntPtr target)
{
...
}
public Entity Foo { get; set; }
public Test()
{
this.Foo = new Body.Sphere() { Visible = false }; // Irrelevant
this.Foo.CollisionType = 3; // Irrelevant
this.Call = new EntityCallback(this.Bar);
this.Foo.SetCallback(this.Call, EntityCallbackType.Collision);
}
}
You didn't read it correctly. You must do this:
...change your code to keep a reference to that delegate on the managed side for the lifetime of the marshaled unmanaged function pointer.
In other words, just store a reference to the delegate instance in your class and make sure the class object survives long enough. Use a static if you really have to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With