【开源三方库】Aki:一行代码极简体验JS&C++跨语言交互
开源项目 OpenHarmony
是每个人的 OpenHarmony

一、简介
OpenAtom OpenHarmony(以下简称“OpenHarmony”)的前端开发语言是ArkTS,在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是JavaScript(简称JS)的超集。而Node-API(简称NAPI)是方舟引擎用于封装JS能力为Native插件的API,是前端JS与Native C/C++的FFI(Foreign Function Interface 跨语言交互接口)。
Aki——针对OpenHarmony上提供JS与C/C++跨语言互调的场景提供解决方案,提供了复杂度仅为O(1)级别的极简语法糖使用方式,一行代码完成JS与C/C++的无障碍跨语言互调,所键即所得。同时开发者无需关心NAPI的线程安全问题、Native对象GC问题,为开发者屏蔽NAPI内部复杂逻辑。

OpenHarmony中NAPI的用法不在本文阐述,不然就有点像孔乙己“茴香豆有几种写法”的感觉了。感兴趣的可以参考OpenHarmony关于Native API使用指导。而开发者使用NAPI过程中还会发现:为了做跨线程任务,需要做线程管理,需要关心环境上下文;为了使用结构体对象,需要关注napi_value生命周期如何管理;巴拉巴拉等等与自己业务无关的逻辑。搞了半天,发现业务代码一行没写,还在写NAPI的跨语言调用实现。拥有洁癖的开发者还会发现,很难做到隔离NAPI代码与业务代码,我们讨厌毫无边界性的编程。
二、所键即所得:NAPI的尽头就是Aki

归根结底NAPI要做的就是FFI即跨语言调用,而开发者重视的是自己的业务逻辑而不是如何做跨语言调用:我就想把大象放进冰箱,你非要告诉我:先打开冰箱,然后抬起大象放进去,再关上冰箱。开发者想要的就是直截了当指明这个函数是个跨语言调用函数。Aki提供了JSBind语法糖,就做了这么一件事,开发者集成后,完全做到一行代码:所键即所得,并把业务代码与FFI代码完美隔离,提供了友好的边界性编程体验。
示例一:同步异步接口封装
示例一期望将C++业务逻辑(GetName)注册为JS同步接口(getSync)、异步接口(getAsync),Aki提供了极简的JSBind函数绑定语法糖,一行代码绑定跨语言调用接口:
● C/C++ Code
#include // C++业务逻辑
std::string GetName(std::string key)
{
std::string result = ...... // 获取数据的业务逻辑 return result; // 返回字符串类型
} // Aki JSBind语法糖
JSBIND_ADDON(task_runner);
JSBIND_GLOBAL() {
JSBIND_FUNCTION(GetName, "getNameSync"); // 绑定同步方法
JSBIND_PFUNCTION(GetName, "getNameAsync"); // 绑定异步方法
}
● JavaScript Code
import libtask_runner from 'libtask_runner.so';
const name = libstorage.getNameSync('name');// 调用同步方法
console.log('name is ' + name);
// 调用异步方法
libstorage.getNameAsync('name').then(date => {
console.log('name is ' + data);
}).catch(error => {
console.log('error: ' + error);
});
示例二:Native与JS对象绑定
示例二期望将C++结构体/类对象(Person)逻辑注册为JS类对象(Person),包含类构造函数+类成员函数+类静态函数+类属性访问等特性,通知支持类对象作为参数及返回值。Aki提供了极简的JSBind对象绑定语法糖,开发者无需关注Native对象内存与JS引擎GC垃圾回收关系,直接绑定Native对象:
● C/C++ Code
#include
// C++逻辑
struct Person {
// 构造函数,用于JS侧 new 对象
Person(std::string name) : name(name) {}
// 静态函数
static Person GetAllPerson(); // 支持类对象作为参数
// 成员函数
int SayHello();
std::string name;
};
// Aki JSBind语法糖
JSBIND_ADDON(person);
JSBIND_CLASS(Person) {
JSBIND_CONSTRUCTOR(); // 绑定构造函数
JSBIND_METHOD(GetAllPerson); // 绑定类静态函数
JSBIND_METHOD(SayHello); // 绑定类成员函数
JSBIND_PROPERTY(name); // 绑定类成员属性
}
● JavaScript Code
import libperson from 'libperson.so';
let person = new libperson.Person("aki"); // 调用构造函数
console.log('person name: ' + person.name); // 访问类属性
let greeting = person.SayHello(); // 调用类成员函数
let persons = libperson.Person.GetAllPerson(); // 调用类静态函数
示例三:在非JS线程中回调JS接口
示例三期望在非JS线程中回调JS接口,Aki提供了线程安全的JSBind语法糖,开发者无需关注JS线程安全问题——OpenHarmony方舟引擎规定JS回调的任务必须抛到JS线程中才能执行,否则会出现崩溃(即Native侧只能在JS线程使用NAPI)。
● C/C++ Code
#include
// C++逻辑
void SafetyCallback(std::function<void (std::string)> callback) {
std::thread t([callback = std::move(callback)] () {
callback("aki"); // 线程安全,直接调用
});
t.detach();
}
// Aki JSBind语法糖
JSBIND_ADDON(sub_thread);
JSBIND_GLOBAL() {
JSBIND_FUNCTION(SafetyCallback);
}
● JavaScript Code
import libsub_thread from 'libsub_thread.so';
// 入参为JS方法回调
libsub_thread.SafetyCallback((data) => {
console.error('test result = ' + data); // test result = aki
})
示例四:Native调用绑定JS函数
示例四期望在C/C++侧调用JS接口(非回调)创建rdb关系型数据库表。Aki提供了JS侧的内建JSBind语法糖,开发者可直接绑定JS侧函数供Native侧调用。
● JavaScript Code
import libAddon from 'libaddon.so'
function createTable(table: string) {
rdbStore.executeSql()... // OHOS 关系型数据库逻辑
}
libAddon.JSBind.bindFunction('createTable', createTable); // 绑定JS函数
● C/C++ Code
#include // C++逻辑
bool DoSomethingFromNative() {
if (auto createTable = aki::JSBind::GetJSFunction("createTable")) {
createTable->Invoke("MYSTORE"); // 入参类型 string
}
示例五:类型转换
Aki支持丰富的类型转换,几乎所有JS的数据类型都可以通过Aki映射为同等的C/C++数据类型,开发者无需处理类型转换,如上述示例用法,框架支持自动匹配类型转换,下表为当前支持的完整类型转换关系:

三、集成依赖Aki
1. 创建平台工程
DevEco Studio 创建包含Native C++的工程
File > New > Create Project | Module
2. 配置依赖并安装
● ohpm三方组件依赖:@ohos/aki
指定模块路径下(如:项目根路径/entry),输入如下命令安装ohpm har包依赖:
cd entry
ohpm install @ohos/aki
CMakeLists.txt添加依赖:
...
set(AKI_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules/@ohos/aki) # 设置AKI根路径
set(CMAKE_MODULE_PATH ${AKI_ROOT_PATH})
find_package(Aki REQUIRED)
...
target_link_libraries(${YOUR_TARGET} PUBLIC Aki::libjsbind) # 链接二进制依赖
...
● 源码依赖
用户自定义路径下(如:项目根路径/entry/src/main/cpp),输入如下命令下载源码:
cd entry/src/main/cpp
git clone https://gitee.com/openharmony-sig/aki.git
CMakeLists.txt添加依赖:
...
add_subdirectory(aki)
target_link_libraries(entry PUBLIC aki_jsbind) // entry 为编译目标
...
3. 编译工程&运行
完成!!!
相关链接
《Aki使用指导》
https://gitee.com/openharmony-sig/aki
《Aki example》
https://gitee.com/openharmony-sig/aki/tree/master/example/ohos
OpenHarmony三方库中心仓
https://ohpm.openharmony.cn/#/cn/home
DevEco Studio
https://developer.harmonyos.com/cn/develop/deveco-studio/
Native API使用指导
https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/napi/napi-guidelines.md/
【开源三方库】Aki:一行代码极简体验JS&C++跨语言交互的更多相关文章
- 极简的js点击组图切换效果
程序员进行前端开发时,时常要用到点击切换组图的动画效果,网上确实有很多此类插件,但是都很麻烦,乌糟糟无数代码,有那个看的时间,自己都能把功能写完了.在这里我提供一段极简的js点击组图切换效果代码,包含 ...
- 极简 Node.js 入门 - 2.3 process
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- js 日期计算星座 根据生日的月份和日期,一行代码计算星座的js小函数(转)
本博客根据 开源中国作者清风徐不来 的文章 根据生日的月份和日期,一行代码计算星座的js小函数(转) 原文出自CSDN 无心的专栏 的文章,知识产权归原文作者所有! 点击查看原文:js 日期计算星座
- 极简 Node.js 入门 - Node.js 是什么、性能有优势?
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 1.2 模块系统
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 1.3 调试
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 1.4 NPM & package.json
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 3.1 File System API 风格
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 4.2 初识 stream
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- 极简 Node.js 入门 - 4.3 可读流
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
随机推荐
- OpenCV开发笔记(六十六):红胖子8分钟带你总结形态学操作-膨胀、腐蚀、开运算、闭运算、梯度、顶帽、黑帽(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- 7z命令
文件解压缩命令 语法格式:7z 参数 文件名 常用参数 a 向压缩包中添加文件 t 测试压缩包的完整性 d 从压缩包中删除文件 u 更新压缩包中的文件 e 从压缩包中提取文件 x 解压文件时保留绝对路 ...
- 【算法day3】小和、荷兰国旗、快排
小和问题 现有数组[1,3,4,2,5] 1左边是0(小于1),所以1的小和为0 3左边是1(小于3),所以3的小和为1 4左边是1.3(均小于4),所以4的小和为1+3=4 2左边是1.3.4(只有 ...
- [软件工程] CMMI是什么?
序 能力成熟度模型集成(CMMI) 一.CMMI(能力成熟度模型集成)概述 CMMI是由美国软件工程学会(software engineering institue,简称SEI)制定的一套专门针对软件 ...
- RabbitMQ零碎整理,总有一天在你工作中会用到
概念 MQ:消息队列(消息中间件),开源的基于AMQP协议的消息中间件,异步 解耦 削峰 核心作用:1.异步 2.解耦 3.消息通信 RabbitMQ 消息的类型:1.点对点 2.Worker 3.发 ...
- 用BootstrapBlazor制作修改订单字段的页面
1.在Shared文件夹下新增一个razor 2.页面初始化的时候获取订单信息 准备一个名为OrderId的参数 准备重写页面初始化时的方法 改成异步的形式来重写 4.获取数据 就3行代码. 声明这个 ...
- 可视化技术在 Nebula Graph 中的应用
本文首发于 Nebula Graph Community 公众号 本文整理自 #可视化 on Live 主题直播,在本期直播中 3 位可视化嘉宾讲述了他们眼中的可视化,以及他们在可视化项目实践中踩过的 ...
- Dungeon Master 题解
这道题的题意简单来说:就是在3D迷宫里找出口,也就是三维地图,需要用到三维数组 由于本人写代码极易出错,所以在输入三维数组的时候修改了c(column,即列)的值,重复定义了没看到==,后面改成定义成 ...
- 聚焦企业流程智能化发展新趋势,中国信通院2022 RPA创新产业峰会即将开启
机器人流程自动化(Robotic Process Automation,RPA)是数字时代的重要劳动力之一,流程的自动化.智能化运行是企业释放运营能效.提升客户服务水平的重要路径. 近年来,各行业对R ...
- Kubernetes CKA考试之Killer Simulator(下)
写在前面 个人微信公众号:密码应用技术实战 个人博客园首页:https://www.cnblogs.com/informatics/ 注:学习交流使用 目录 写在前面 Question 16 | Na ...