在摆动中玩转目标-丙块

云栖息地编号信息:[点击查看更多行业信息]

在这里,您可以找到来自不同行业的第一手云信息。你还在等什么?来吧。

Dart_native作为一个性能比Channel更高、开发成本更低的超级Channel,通过C调用nativeAPI,深入底层,综合考虑。许多Objective-C接口的参数和返回值都是Block,因此有必要支持用Dart语言创建和调用Objective-C块。

Dart 调用 Objective-C 带 Block 的 API

Dart支持coroutine,它消除了作为异步调用回调的传递闭包的需要。然而,大量的Objective-C API使用Block作为回调。当Dart调用这样的异步API时,Dart端需要创建块并将其传递给objective-c

Dart语言中的函数可以用作闭包,它可以实现以下效果:

在摆动中玩转目标-丙块

相应的目标-客户界面如下:

在摆动中玩转目标-丙块

让我们来讨论一下dart_native如何将dart函数作为一个块传递给Objective-C。

函数签名

首先要确保镖函数的签名与目标-C块一致,以便两者可以转换。在达特中,一切都是一个对象,函数也不例外。然后获取函数的runtimeType并解析其内容。然而,runtimeType的内容都是Dart类名。它们如何对应目标-C类型?Dart_native的策略是提供与native同名的类,因此使用这些类来定义Dart函数可以将函数签名映射到Native。

列出Dart声明的一些基本类型:

在摆动中玩转目标-丙块

动态创建 Block

有了函数签名,如何构造相应的块对象?首先要知道的是什么是Block,这是另一个老话题。我强烈建议您首先理解BlockHook及其相关文章,这将对理解这部分内容有很大帮助。

不用说,在核心问题上:

在摆动中玩转目标-丙块

在摆动中玩转目标-丙块

在摆动中玩转目标-丙块

简单地说,动态创建块的过程封装在一个包装类中,步骤如下:

使用libffi动态创建具有相同签名的函数,

准备好创建标志、描述、签名、包装对象等。Block要求。

根据块的内存模型,创建相应的结构(在堆栈上)

将块对象复制到堆中,并发送一条自动释放消息。

事实上,上面的每一步都不简单。如果你把它分开,你可以写一段。然而,既然大爆炸已经写了一篇文章介绍它,我就不在这里重复了。我只是站在巨人的肩膀上,给Dart增加了一些改进和适应(比如支持结构、x86兼容性等)。)。惭愧的是,我做了一点工作。

映射 Block 和 Dart Function

创建块对象后,需要用镖函数映射它,然后在执行块之前不会调用相应的镖逻辑。

关于回调,我在Dart端维护了一个映射来管理从本机到Dart的回调映射。基本思想是键是本机对象的地址,值是Dart端的Block类。

映射将在块类构造方法的Dart版本中建立:

在摆动中玩转目标-丙块

该映射将在块类的dealloc方法中被删除,以防止Dart版本的“通配符指针”。

在摆动中玩转目标-丙块

Dart 调用 Objective-C 返回的 Block

基于对Block的理解和Dart调用OC方法的经验,在Block的Dart版本中很容易实现调用方法:

在摆动中玩转目标-丙块

在摆动中玩转目标-丙块

简单来说上面的实现做了如下几步:

获取块的函数签名

验证Dart测试传入的参数列表,看它是否与函数签名匹配

Dart参数被转换为对应于本机的类型,并写入堆中

调用C函数块调用来传递块指针和参数列表辅助指针

释放辅助指针(它所指向的对象类型和堆上的结构将被自动释放)

将块调用返回的指针内容转换为Dart对象

后续

事实上,还有许多关于Block的技术细节没有被充分描述,包括复制方法的实现、回调映射的细节以及自动类型转换的细节。出于空间原因,感兴趣的人可以直接查看源代码:https://github.com/dart-native/dart_native

事实上,我期望的是使用Dart的协调过程来处理异步回调,这更加现代和优雅。将来,上层接口将基于该方案再次封装,以支持协调。

Dart_native作为从Dart到native的超级通道,深入到底层并考虑了所有方面,在未来仍有许多工作要做。

[云起在线教室]产品和技术专家每天分享!

课程地址:https://yqh.aliyun.com/live

立即加入社区,与专家面对面,并了解课程的最新进展!

[云栖在线课堂社区]https://c.tb.cn/F3.Z8gvnK

发布者:2020-04-15

作者:杨萧玉

本文来源于“玉造世界博客”,了解相关信息可以关注“玉造世界博客”