문제

I'm writing a wrapper around some C code, and I can't quite figure out how to write this bit without being able to use the ref keyword in a lambda.

The unmanaged function wrappers look like this:

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

But I don't want to use SDL_Event directly (it's a complicated struct), so I've wrapped it in my own class, Event. However, C is expecting a pointer to an SDL_Event not an Event so I have to write some more code to wrap it all up:

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

This basically takes the SDL_Event that I'm given and converts it into my Event class. However, I can't use the ref keyword inside a lambda, but I'm not sure how to get around it.

I could define a regular helper method instead of using a lambda, but I need to use the local filter variable inside of it, and I don't know how to get that into the function without changing the signature (then it wouldn't match SDL_EventFilter).

In JavaScript, PHP, or Python I could construct a callable object, make filter a member variable, and then use the object as the callback. I'm not sure if there's a similar concept in C#, is there?

도움이 되었습니까?

해결책

When using the ref keyword, the type must also be given. Like this:

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

The parameter list of a lambda is like the parameter list of an ordinary named method. The types can be left out in a lambda, however, but only when no parameters have modifyers such as ref, out, params.

다른 팁

Yes you can't do it since Lambda actually captures the variable in CompilerGenerated class and reuses it.

We can make use of ref keyword while passing to a method, but still if you capture the parameter to someother variable It wont behave as you expect.

So easy workaround will be create a method and use instead of lambda.

Something like this (untested):

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);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top