我正在包装一个使用 MonoDevelop 进行回调的块的 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 获取托管用户类。相反,我得到一个指向非托管用户类的指针。所以它是这样工作的:
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.它要求用户明确声明“不安全”,属性(无法阻止)并实际将指针传递给包装类,这样他/她就会有一个“用户”的漂亮 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?
}
无法运行回调。所以我尝试了匿名委托(或 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 上不起作用。
除了让用户专门包装他/她自己不满足我的指针之外,我找不到任何其他方法来解决它。考虑过使用静态数组来存储回调,但我无法真正将返回的内部回调与我想要调用的回调匹配(或者我可以吗?)
有什么建议么?:)
编辑:我想我只是想在原始回调和调用者之间添加一个回调桥——就像一个中间人。但我不能用匿名代表来做这件事。有没有办法做到这一点?