2

私はいくつかの C コードのラッパーを書いていますがref、 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(複雑な構造体です) ので、独自のクラスでラップしましたEventSDL_Eventただし、C は非 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ラムダ内でキーワードを使用することはできませんが、それを回避する方法がわかりません。

ラムダを使用する代わりに通常のヘルパー メソッドを定義することもできますが、そのfilter内部でローカル変数を使用する必要があり、署名を変更せずにそれを関数に取り込む方法がわかりません (その場合、一致しませんSDL_EventFilter) 。 .

JavaScript、PHP、または Python では、呼び出し可能なオブジェクトを構築しfilter、メンバー変数を作成して、そのオブジェクトをコールバックとして使用できます。C# に同様の概念があるかどうかはわかりませんが、ありますか?

4

3 に答える 3

3

キーワードを使用する場合refは、タイプも指定する必要があります。このような:

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

ラムダのパラメーター リストは、通常の名前付きメソッドのパラメーター リストに似ています。ただし、ラムダでは型を省略できますが、これは、、、などの修飾子がパラメーターにない場合に限られrefます。outparams

于 2013-08-05T22:14:45.063 に答える
2

Lambdaはい、実際にはクラス内の変数をキャプチャしてCompilerGenerated再利用するため、できません。

メソッドに渡すときにキーワードを使用できrefますが、パラメーターを別の変数にキャプチャする場合でもIt wont behave as you expect.

簡単な回避策は、ラムダの代わりにメソッドを作成して使用することです。

于 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 に答える