将委托定义为函数指针

时间:2010-09-11 17:12:52

标签: c# delegates unmanaged function-pointers

我正在使用一个调用非托管函数指针的委托。这会导致垃圾收集器在使用之前收集它,如MSDN上的CallbackOnCollectedDelegate MDA页面中所述:MSDN page for CallbackOnCollectedDelegate MDA

该决议声明我必须将适当的委托编组为非托管函数指针。我最初的反应是使用:

[MarshalAs(UnmanagedType.FunctionPtr)]
public delegate void EntityCallback([MarshalAs(UnmanagedType.SysInt)] IntPtr entity);

但是,C#编译器不会让我编组一个委托,即使这是MSDN建议的解决方案。此外,MSDN页面仅显示抛出问题的示例,但不是解决方案之一。

我如何将我的委托编组为非托管函数指针或使其不被GC控制?

编辑:根据建议,我创建了回调的引用。因此,我的代码从/更改为:

// From:
foo.SetCallback(new EntityCallback(bar));

// To:
call = new EntityCallback(bar); // Referenced in class
foo.SetCallback(call);

现在这确实有效 - 但仅限于调试模式。当我切换到Release时,它会在同一点崩溃。那是为什么?

编辑2 :更完整的代码段:

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);
    }
}

1 个答案:

答案 0 :(得分:9)

您没有正确阅读。你必须这样做:

  

...更改您的代码以保留参考   管理方面的代表   在整理的一生中   非托管函数指针。

换句话说,只需在类中存储对委托实例的引用,并确保类对象能够存活足够长的时间。如果你真的需要,请使用静态。