在回调中包装回调,以便在C#和Objective-C之间使用monodevelop进行互操作

时间:2012-12-27 14:00:33

标签: c# objective-c callback interop monodevelop

我正在使用Mono -velop包装一个Obj-C api,它使用块进行回调。我设法将我的C#委托连接到Objective-C中的一个块,只要我用[MonoPInvokeCallback]装饰它们就可以正常工作,因此它可以编译AOT。

在块返回类实例之前,这一切都很好。这让我回到C#指向类的指针(我的实现中的IntPtr)。通常当我从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);
}

这可行,但它有两种方面很难看: 1.它要求用户专门声明“unsafe”,属性(无法阻止)并实际将指针传递给包装类,这样他/她就会有一个很好的C#接口“User”。

我试过这样做: 在调用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?
}

无法运行回调。所以我尝试了匿名委托(或lambda):

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属性进行修饰,而且它的编译JIT在iphone上不起作用。

我找不到任何其他方法来解决它,除了让用户专门包装他/她自己不满足我的指针。考虑使用静态数组来存储回调,但我无法将返回的内部回调与我想要调用的回调相匹配(或者我可以吗?)

有什么建议吗? :)

编辑:我想我只是想在原始回调和来电者之间添加一个回调桥 - 就像中间人一样。但我不能与匿名代表这样做。有没有办法做到这一点?

0 个答案:

没有答案