MonoDevelop を使用して、コールバックにブロックを使用する Obj-C API をラップしています。C# デリゲートを Objective-C のブロックに接続することができました。[MonoPInvokeCallback] でデコレートして AOT をコンパイルする限り、正常に動作します。
ブロックがクラス インスタンスを返すまでは問題ありません。これにより、クラスへのポインター (私の実装では IntPtr) が C# に返されます。通常、Obj-C から呼び出すメソッドがこのポインターを返す場合、ハンドルを独自のマネージ クラスでラップし、そこからすべてのメソッドを呼び出します。ラップされたハンドルに優れた C# インターフェイスを提供します。この特定のケースでは、IntPtr がユーザー作成のコールバックに直接呼び出されるため、適切にラップする機会がありません。
delegate void GetUserCallback(User user);
//User callback
[MonoPInvokeCallback (typeof (GetUserCallback))]
void PrintUserName(User user) {
Console.WriteLine(user.name);
}
void GetUserById (int id, GetUserCallback callback) {
ApiGetUserById(id, callback);
}
Objective-C からマネージド User クラスを取得できないため、これは機能しません。代わりに、アンマネージ User クラスへのポインターを取得します。したがって、次のように機能します。
delegate void GetUserCallbackPtr(IntPtr userPtr);
//User callback
[MonoPInvokeCallback (typeof (GetUserCallbackPtr))]
unsafe void PrintUserName(IntPtr userPtr) {
User user = new User(userPtr);
Console.WriteLine(user.name);
}
void GetUserById (int id, GetUserCallbackPtr callback) {
ApiGetUserById(id, callback);
}
これは機能しますが、2 つの点で見苦しくなります。 「ユーザー」への素敵な C# インターフェイス。
私はこれをやってみました:APIを呼び出してコールバックを提供するメソッドで、IntPtrを取得してラップし、それを使用して元のコールバックを呼び出す新しいコールバックを作成します-たとえば、次のように:
delegate void GetUserCallback(User user);
delegate void GetUserCallbackPtr(IntPtr userPtr);
//User callback
void PrintUserName(User user) {
Console.WriteLine(user.name);
}
void GetUserById (int id, GetUserCallback callback) {
ApiGetUserById(id, InnerCallback);
}
[MonoPInvokeCallback (typeof (GetUserCallbackPtr))]
void InnerCallback(IntPtr userPtr) {
// How do I run the original "callback" from here?
}
コールバックを実行できません。だから私は匿名デリゲート(またはラムダ)を試しました:
delegate void GetUserCallback(User user);
delegate void GetUserCallbackPtr(IntPtr userPtr);
//User callback
void PrintUserName(User user) {
Console.WriteLine(user.name);
}
void GetUserById (int id, GetUserCallback callback) {
ApiGetUserById(id, delegate(IntPtr userPtr) {
callback(userPtr);
});
}
匿名デリゲートは MonoPInvokeCallback 属性で装飾されておらず、iPhone では動作しないコンパイル済みの JIT であるため、これも動作しません。
ユーザーにポインタを自分で具体的にラップさせる以外に、それを解決する方法が見つかりませんでした。これは私を満足させません。コールバックを格納するために静的配列を使用することを考えましたが、返された内部コールバックを呼び出したいコールバックに実際に一致させることはできません (またはできますか?)
助言がありますか?:)
編集:私は、元のコールバックと発信者の間にコールバック ブリッジを追加しようとしているだけだと思います-仲介者のように。しかし、匿名のデリゲートではこれを行うことはできません。それを行う方法はありますか?