2

ref我正在围绕一些 C 代码编写一个包装器,如果不能在 lambda 中使用关键字,我无法弄清楚如何编写这个位。

非托管函数包装器如下所示:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int SDL_EventFilter(ref object userData, ref SDL_Event @event);

[DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_AddEventWatch")]
internal static extern void SDL_AddEventWatch(SDL_EventFilter filter, ref object userData);

但是我不想SDL_Event直接使用(它是一个复杂的结构),所以我将它包装在我自己的类中,Event. 但是,C 期望一个指向SDL_Eventnot an的指针,Event所以我必须编写更多代码来包装它:

public delegate void EventFilter(object userData, Event @event);

public static void AddEventWatch(EventFilter filter, object userData)
{
    SDL_AddEventWatch((ref data, ref e) =>        // <-- can't do this
    {
        filter(data, new Event(ref e));
        return 0;
    }, ref userData);
}

这基本上采用了SDL_Event我给出的并将其转换为我的Event课程。但是,我不能ref在 lambda 中使用关键字,但我不确定如何绕过它。

我可以定义一个常规的辅助方法而不是使用 lambda,但是我需要在其中使用局部filter变量,而且我不知道如何在不更改签名的情况下将其放入函数中(那么它就不会匹配SDL_EventFilter) .

在 JavaScript、PHP 或 Python 中,我可以构造一个可调用对象,创建filter一个成员变量,然后将该对象用作回调。我不确定C#中是否有类似的概念,有吗?

4

3 回答 3

3

使用ref关键字时,还必须给出类型。像这样:

(ref object data, ref SDL_Event e) => { ... }

lambda 的参数列表类似于普通命名方法的参数列表。但是,这些类型可以在 lambda 中省略,但前提是没有参数具有修饰符,例如ref, out, params

于 2013-08-05T22:14:45.063 回答
2

是的,您不能这样做,因为Lambda实际上捕获了CompilerGenerated类中的变量并重用它。

我们可以ref在传递给方法时使用关键字,但如果您将参数捕获到其他变量,仍然可以It wont behave as you expect

如此简单的解决方法将是创建一个方法并使用而不是 lambda。

于 2013-08-05T22:15:58.747 回答
1

像这样的东西(未经测试):

class Capture
{
    private readonly EventFilter filter;

    public Capture(EventFilter filter)
    {
        this.filter = filter;
    }

    public int Method(ref object userData, ref SDL_Event @event)
    {
        this.filter(userData, new Event(ref event));
        return 0;
    }
}

public static void AddEventWatch(EventFilter filter, object userData)
{
    var capture = new Capture(filter);
    SDL_AddEventWatch(capture.Method, ref userData);
}
于 2013-08-05T22:38:57.430 回答