Определение делегата в качестве указателя на функцию - PullRequest
5 голосов
/ 11 сентября 2010

Я использую делегат, который вызывает указатель неуправляемой функции.Это приводит к тому, что сборщик мусора собирает его перед его использованием, как описано на странице MDA CallbackOnCollectedDelegate на MSDN: Страница MSDN для MDB CallbackOnCollectedDelegate .

В разрешении указывается, что необходимо выполнитьсоответствующий делегат как указатель неуправляемой функции.Мой первоначальный рефлекс заключался в использовании:

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

Однако компилятор C # не позволит мне маршалировать делегата, даже если это предложенное MSDN разрешение.Кроме того, на странице MSDN показан только пример проблемы, но не одно из ее решений.

Как я могу маршалировать свой делегат как указатель неуправляемой функции или не допустить его GCed?

РЕДАКТИРОВАТЬ : Как и предполагалось, я создал ссылку на обратный вызов.Поэтому мой код изменился с / на:

// 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 Ответ

9 голосов
/ 11 сентября 2010

Вы не правильно прочитали.Вы должны сделать следующее:

... изменить свой код, чтобы сохранить ссылку на этого делегата на управляемой стороне на время жизни указателя неуправляемой функции маршалирования.Другими словами, просто сохраните ссылку на экземпляр делегата в вашем классе и убедитесь, что объект класса сохранился достаточно долго.Используйте статический, если вам действительно нужно.

...