将委托定义为函数指针

Laz*_*zlo 5 c# delegates unmanaged function-pointers

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

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

[MarshalAs(UnmanagedType.FunctionPtr)]
public delegate void EntityCallback([MarshalAs(UnmanagedType.SysInt)] IntPtr entity);
Run Code Online (Sandbox Code Playgroud)

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

我如何作为非托管函数指针封送我的委托或阻止它被GCed?

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

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

// To:
call = new EntityCallback(bar); // Referenced in class
foo.SetCallback(call);
Run Code Online (Sandbox Code Playgroud)

现在这确实有效 - 但仅在调试模式下.当我切换到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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 9

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

...更改代码以在封送的非托管函数指针的生命周期内保持对托管端的该委托的引用.

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