AKI 项目介绍
AKI (Alpha Kernel Interacting)
是一款边界性编程体验友好的ArkTs FFI开发框架,针对OpenHarmony Native开发提供JS与C/C 跨语言访问场景解决方案。支持极简语法糖使用方式,一行代码完成JS与C/C 的无障碍跨语言互调,所键即所得。
优势
- 极简使用,解耦FFI代码与业务代码,友好的边界性编程体验;
- 提供完整的数据类型转换、函数绑定、对象绑定、线程安全等特性;
- 支持JS & C/C 互调;
- 支持与Node-API嵌套使用;
已测试兼容环境
- OpenHarmony(API 10) SDK (4.0.9.6): 通过
- DevEco Studio (4.0.0.400): 通过
- OpenHarmony(API 9) SDK (3.2.12.2): 通过
- DevEco Studio (3.1.0.500): 通过
1 依赖配置(2选1)
- 源码依赖(推荐)
指定cpp路径下(如:项目根路径/entry/src/main/cpp)
代码语言:shell复制 cd entry/src/main/cpp
git clone https://gitee.com/openharmony-sig/aki.git
CMakeLists.txt添加依赖(假定编译动态库名为:libhello.so):
代码语言:c复制 add_subdirectory(aki)
target_link_libraries(hello PUBLIC aki_jsbind)
- ohpm har包依赖
指定路径下(如:项目根路径/entry),输入如下命令安装ohpm har包依赖
代码语言:shell复制 cd entry
ohpm install @ohos/aki
CMakeLists.txt添加依赖(假定编译动态库名为:libhello.so):
代码语言:c复制 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(hello PUBLIC Aki::libjsbind) # 链接二进制依赖 & 头文件
2 用户自定义业务
用户业务 C 代码 hello.cpp:
全程无感node-API
#include <string>
std::string SayHello(std::string msg)
{
return msg " too.";
}
3 使用 AKI
使用JSBind
工具宏声明需要被绑定的类、函数:
#include <aki/jsbind.h>
// Step 1 注册 AKI 插件
JSBIND_ADDON(hello) // 注册 AKI 插件名: 即为编译*.so名称,规则与NAPI一致
// Step 2 注册 FFI 特性
JSBIND_GLOBAL()
{
JSBIND_FUNCTION(SayHello);
}
4 编译构建使用
OpenHarmony工程代码调用:
代码语言:js复制import aki from 'libhello.so' // 工程编译出来的*.so
aki.SayHello("hello world");
JSBind 语法糖
插件注册
JSBIND_ADDON(addonName)
使用JSBIND_ADDON
注册OpenHarmony Native 插件,可从 JavaScript import
导入插件。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
addonName | Y | 注册的OpenHarmony native 插件名,可从 JavaScript |
示例:
- C
#include <string>
#include <aki/jsbind.h>
JSBIND_ADDON(addon0)
- JavaScript
import addon from 'libaddon0.so' // 插件名为:addon0
JSBIND_ADDON_X(addonName constructorAlias)
用法与JSBIND_ADDON
相似,用于支持插件名有特殊符号的场景,如包含'-';
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
addonName | Y | 注册的OpenHarmony native 插件名,可从 JavaScript | |
constructorAlias | Y | 插件预构造函数名,只需填写符合函数命名规则名称即可,无其他特殊含义 |
示例:
- C
#include <string>
#include <aki/jsbind.h>
JSBIND_ADDON(hello-world, HelloWorld)
- JavaScript
import addon from 'libhello-world.so' // 插件名为:hello-world
绑定全局函数
JSBIND_GLOBAL
用于圈定需要绑定的全局函数 scope。
JSBIND_FUNCTION(func, alias)
在JSBIND_GLOBAL
作用域下使用JSBIND_FUNCTION
绑定 C 全局函数后,可从 JavaScript 直接调用。
- 调度线程为 JS 线程;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
func | 函数指针 | Y | 被绑定的 |
alias | string | N | 函数别名 |
示例:
- C
#include <string>
#include <aki/jsbind.h>
std::string SayHello(std::string msg)
{
return msg " too.";
}
JSBIND_GLOBAL()
{
JSBIND_FUNCTION(SayHello);
}
JSBIND_ADDON(hello);
- JavaScript
import aki from 'libhello.so' // 插件名
let message = aki.SayHello("hello world");
JSBIND_PFUNCTION(func, alias)
使用JSBIND_PFUNCTION
绑定 C 全局函数后,从 JavaScript 使用同Promise方式相同的异步调用。
- 调度线程为工作线程,由 ArkCompiler Runtime 决定;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
func | 函数指针 | Y | 被绑定的 |
alias | string | N | 函数别名 |
示例:
- C
int AsyncTaskReturnInt() {
// Do something;
return -1;
}
JSBIND_GLOBAL() {
JSBIND_PFUNCTION(AsyncTaskReturnInt);
}
JSBIND_ADDON(async_tasks);
- JavaScript
import libAddon from 'libasync_tasks.so'
libAddon.AsyncTaskReturnInt().then(res => {
console.log('[AKI] AsyncTaskReturnInt: ' res)
});
绑定类/结构体
AKI
提供 JSBIND_CLASS
对 C 类/结构体
进行绑定,在JSBIND_CLASS
作用域下可绑定:类构造函数、类成员函数、类成员属性的类特性。
JSBIND_CLASS(class)
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
class | class/struct | Y | 被绑定的C |
JSBIND_CONSTRUCTOR<T>()
在JSBIND_CLASS
作用域下使用绑定 C 类/结构体构造函数,其中为了支持多态,可通过类型模板指定构造函数参数类型。
JSBIND_CONSTRUCTOR
需要在JSBIND_CLASS
的作用域下;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
T | any | N | 构造函数参数类型,可变类型参数。 |
示例:
- C
#include <string>
#include <aki/jsbind.h>
class TestObject {
public:
TestObject();
explicit TestObject(double) {
// ...
}
~TestObject() = default;
} // TestObject
JSBIND_CLASS(TestObject)
{
JSBIND_CONSTRUCTOR<>();
JSBIND_CONSTRUCTOR<double>();
}
JSBIND_ADDON(hello);
- JavaScript
import aki from 'libhello.so' // 插件名
var obj1 = new aki.TestObject();
var obj2 = new aki.TestObject(3.14);
绑定类成员函数
JSBIND_METHOD(method)
AKI
使用 JSBIND_METHOD
对C 的3种类成员函数进行绑定:类静态函数、类成员函数、const 类成员函数。
JSBIND_METHOD
需要在JSBIND_CLASS
的作用域下;- 调度线程为 JS 线程;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
method | R (C::*)(P...) | Y | 同时支持类静态函数、类成员函数、const 类成员函数。 |
示例:
使用 AKI
对C 类成员函数绑定
#include <string>
#include <aki/jsbind.h>
class TestObject {
public:
TestObject();
explicit TestObject(double) {
// ...
}
~TestObject() = default;
static double MultiplyObject(TestObject obj1, TestObject obj2) {
return obj1.value_ * obj2.value_;
}
double Multiply(double mult) {
value_ *= mult;
return value_;
}
private:
double value_;
} // TestObject
JSBIND_CLASS(TestObject)
{
JSBIND_CONSTRUCTOR<>();
JSBIND_CONSTRUCTOR<double>();
JSBIND_METHOD(MultiplyObject);
JSBIND_METHOD(Multiply);
}
JSBIND_ADDON(hello);
例:JavaScript 侧调用绑定的C 类成员函数
代码语言:js复制import aki from 'libhello.so' // 插件名
var obj1 = new aki.TestObject();
var obj2 = new aki.TestObject(3.14);
obj1.Multiply(-1);
aki.TestObject.MultiplyObject(obj1, obj2) // 静态方法
JSBIND_PMETHOD(method)
JSBIND_PMETHOD
用于绑定 C 类成员函数,从 JavaScript 使用同Promise方式相同的异步调用。
- 调度线程为工作线程,由 ArkCompiler Runtime 决定;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
method | 类成员函数指针 | Y | 被绑定的 |
示例:
- C
class TaskRunner {
public:
TaskRunner() = default;
std::string DoTask() {
// Do something;
return "done.";
}
};
JSBIND_CLASS(TaskRunner) {
JSBIND_CONSTRUCTOR<>();
JSBIND_PMETHOD(DoTask);
}
int AsyncTaskReturnInt() {
// Do something;
return -1;
}
JSBIND_GLOBAL() {
JSBIND_PFUNCTION(AsyncTaskReturnInt);
}
JSBIND_ADDON(async_tasks);
- JavaScript
import libAddon from 'libasync_tasks.so'
let taskRunner = new libAddon.TaskRunner();
taskRunner.DoTask().then(res => {
console.log('[AKI] DoTask: ' res)
});
libAddon.AsyncTaskReturnInt().then(res => {
console.log('[AKI] AsyncTaskReturnInt: ' res)
});
绑定类成员属性
JSBIND_PROPERTY(property) <sup>new in 1.0.7</sup>
AKI
使用JSBIND_PROPERTY
、JSBIND_FIELD
对 C 的类成员属性、类成员属性访问器进行绑定
JSBIND_PROPERTY
需要在JSBIND_CLASS
的作用域下;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
property | T | Y | 类成员属性名。 |
示例:
代码语言:c复制#include <string>
#include <aki/jsbind.h>
class TestObject {
public:
explicit TestObject(double) {
// ...
}
~TestObject() = default;
private:
double value_;
} // TestObject
JSBIND_CLASS(TestObject)
{
JSBIND_CONSTRUCTOR<double>();
JSBIND_PROPERTY(value);
}
- JavaScript
import aki from 'libhello.so' // 插件名
var obj = new aki.TestObject(3.14);
obj.value = 1;
let value = obj.value;
JSBIND_FIELD(field, getter, setter)
AKI
使用JSBIND_FIELD
对 C 的类成员属性进行监听
JSBIND_FIELD
需要在JSBIND_CLASS
的作用域下;- 调度线程为 JS 线程;
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
field | T | Y | 类成员属性名。 |
getter | T (void) | Y | get属性访问器。 |
setter | void (T) | Y | set属性访问器。 |
示例:
- C
#include <string>
#include <aki/jsbind.h>
class TestObject {
public:
explicit TestObject(double) {
// ...
}
~TestObject() = default;
double GetValue() const {
return value_;
}
void SetValue(double value) {
value_ = value;
}
private:
double value_;
} // TestObject
JSBIND_CLASS(TestObject)
{
JSBIND_CONSTRUCTOR<double>();
JSBIND_FIELD("value", GetValue, SetValue);
}
- JavaScript
import aki from 'libhello.so' // 插件名
var obj = new aki.TestObject(3.14);
obj.value = 1;
let value = obj.value;
绑定枚举类型
JSBind
语法糖JSBIND_ENUM
、JSBIND_ENUM_VALUE
支持绑定 C/C 枚举类型,映射为 JavaScript 的Number类型。
- C/C 侧默认枚举类型为POD中的int32_t;
- JavaScript侧对应的枚举类型属性为
readonly
;
JSBIND_ENUM(enum)
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
enum | enum | Y | 被绑定的 |
JSBIND_ENUM_VALUE(value)
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
value | enum::value | Y | 被绑定的 |
示例:
- C
#include <string>
#include <aki/jsbind.h>
enum TypeFlags {
NONE,
NUM,
STRING,
BUTT = -1
};
JSBIND_ENUM(TypeFlags) {
JSBIND_ENUM_VALUE(NONE);
JSBIND_ENUM_VALUE(NUM);
JSBIND_ENUM_VALUE(STRING);
}
TypeFlags Passing(TypeFlags flag) {
return flag;
}
JSBIND_GLOBAL()
{
JSBIND_FUNCTION(Passing);
}
JSBIND_ADDON(enumeration);
- JavaScript
import libAddon from 'libenumeration.so' // 插件名
console.log('AKI libAddon.TypeFlags.NONE = ' libAddon.TypeFlags.NONE);
console.log('AKI libAddon.TypeFlags.NUM = ' libAddon.TypeFlags.NUM);
console.log('AKI libAddon.TypeFlags.Passing() = ' libAddon.Foo(libAddon.TypeFlags.STRING));
try {
libAddon.TypeFlags.NUM = 10; // TypeError: Cannot set readonly property
} catch (error) {
console.error('AKI catch: ' error);
}
线程安全函数
使用AKI
的线程安全特性,绑定 JavaScript 的业务函数后,可由native
直接调用。
- 线程安全:使用
AKI
线程安全绑定的 JavaScript 函数是线程安全的,可在非JS线程直接调用。最终会由框架调度JS线程执行业务; - 阻塞式调用:C 触发调用 JavaScript 函数的调用是阻塞式的,对于在JS线程执行业务这点没有疑义。但当C 触发 JavaScript 业务调用的线程是非JS线程时,就存在跨线程任务调度。此时由框架进行了阻塞式调用,即 C 会等待 JavaScript 函数执行结束后返回;
JSBind.bindFunction(name: string, func: function)
在 JavaScript 使用 JSBind.bindFunction
绑定 JavaScript 全局函数后,可从 C 直接调用。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
name | string | Y | 指定绑定的 |
func | function | Y | 被绑定的 |
返回值:
类型 | 说明 |
---|---|
number | 当前被绑定的函数下标索引 |
// name: 指定函数名,func: JavaScript 全局函数
libAddon.JSBind.bindFunction(name: string, func: Function);
C 使用aki::JSBind::GetJSFunction获取指定 JavaScript 函数句柄后,使用Invoke触发调用
代码语言:c复制auto jsFunc = aki::JSBind::GetJSFunction("xxx"); // 获取指定函数句柄
auto result = jsFunc->Invoke<T>(...); // 调用JavaScript函数,Invoke<T>指定返回值类型
- JavaScript
import libAddon from 'libhello.so' // 插件名
function sayHelloFromJS (value) {
console.log('what do you say: ' value);
return "hello from JS"
}
libAddon.JSBind.bindFunction("sayHelloFromJS", sayHelloFromJS);
- C
#include <string>
#include <aki/jsbind.h>
void DoSomething() {
// 索引 JS 函数句柄
auto jsFunc = aki::JSBind::GetJSFunction("sayHelloFromJS");
// Invoke 指定 JS 方法的返回值类型
auto result = jsFunc->Invoke<std::string>("hello from C "); // 可在非JS线程执行
// result == "hello from JS"
}
类型转换
JavaScript | C |
---|---|
Boolean |
|
Number |
|
String |
|
Array |
|
Function |
|
Class Object |
|
JsonObject |
|
ArrayBuffer, TypedArray |
|
Promise |
|
any |
|
NOTE: 带有阴影部分的表示已支持
const char*
是以引用方式传递参数,如遇到异步操作,请使用传值方式:std::string
Boolean
如下示例,开发者直接声明函数入参及返回值类型,使用AKI
绑定后,框架自适应对 C/C 的 bool
及 JavaScript 的 Boolean
类型进行转化。
示例:
- C
#include <aki/jsbind.h>
bool Foo(bool flag) {
...
return true;
}
JSBIND_GLOBAL() {
JSBIND_FUNCTION(Foo, "foo");
}
JSBIND_ADDON(hello)
- JavaScript
import libAddon from 'libhello.so'
let flag = libAddon.foo(true);
Number
如下示例,开发者直接声明函数入参及返回值类型,使用AKI
绑定后,框架自适应对 C/C 的 uint8_t
, int8_t
, uint16_t
, int16_t
, short
, int32
, uint32
, int64
, float
, double
, enum
及 JavaScript 的 Number
类型进行转化。
float:
浮点型转换时存在精度丢失,对于高精度场景,请使用double
;
示例:
- C
#include <aki/jsbind.h>
int Foo(int num) {
...
return 666;
}
JSBIND_GLOBAL() {
JSBIND_FUNCTION(Foo, "foo");
}
JSBIND_ADDON(hello)
- JavaScript
import libAddon from 'libhello.so'
let num = libAddon.foo(888);
String
如下示例,开发者直接声明函数入参及返回值类型,使用AKI
绑定后,框架自适应对 C/C 的 const char*
, std::string
及 JavaScript 的 String
类型进行转化。
const char*
是以引用方式传递参数,如遇到异步操作,请使用传值方式:std::string;
示例:
- C
#include <aki/jsbind.h>
std::string Foo(const char* c_str, std::string str) {
...
return "AKI 666";
}
JSBIND_GLOBAL() {
JSBIND_FUNCTION(Foo, "foo");
}
JSBIND_ADDON(hello)
- JavaScript
import libAddon from 'libhello.so'
let str = libAddon.foo("AKI", "666");
Array
如下示例,开发者直接声明函数入参及返回值类型,使用AKI
绑定后,框架自适应对 C/C 的 std::vector<T>
, std::array<T, N>
及 JavaScript 的 []
类型进行转化。
- 数组类型仅支持同种类型的数组声明;
示例:
- C
#include <aki/jsbind.h>
std::vector<double> Foo(std::array<int, 3>) {
std::vector<double> result;
...
return result;
}
JSBIND_GLOBAL() {
JSBIND_FUNCTION(Foo, "foo");
}
JSBIND_ADDON(hello)
- JavaScript
import libAddon from 'libhello.so'
let array = libAddon.foo([1, 2, 3]);
ArrarBuffer
二进制数据缓冲区ArrayBuffer
, TypedArray
是 JavaScript AKI 提供了内建结构体:aki::ArrayBuffer
用来支持该特性:
GetData()*
获取 ArrayBuffer 数组缓冲区地址,aki::ArrayBuffer 本身不申请数据内存,data 都来源于JavaScript引擎分配的内存,也无需做内存生命周期管理,禁止对该内存进行危险的释放。GetLength()
获取 ArrayBuffer 数组缓冲区长度,以单字节为计量单位。GetTyped()
获取 ArrayBuffer 数组缓冲区的类型化类型。GetCount()
获取 ArrayBuffer 数组缓冲区的类型化数据元素个数。
示例:
- C
#include <aki/jsbind.h>
aki::ArrayBuffer PassingArrayBufferReturnArrayBuffer(aki::ArrayBuffer origin) {
aki::ArrayBuffer buff(origin.GetData(), origin.GetCount());
uint8_t* data = buff.GetData();
data[4] = 4;
data[5] = 5;
data[6] = 6;
data[7] = 7;
return buff;
}
- JavaScript
import libAddon from 'libarraybuffer2native.so'
let buff: ArrayBuffer = new ArrayBuffer(8);
let uint8Buff1: Uint8Array = new Uint8Array(buff);
uint8Buff1[0] = 0;
uint8Buff1[1] = 1;
uint8Buff1[2] = 2;
uint8Buff1[3] = 3;
let result: ArrayBuffer = libAddon.PassingArrayBufferReturnArrayBuffer(buff);
uint8Buff1 = new Uint8Array(result);
let message: String = uint8Buff1.toString();
JsonObject
JavaScript支持使用JsonObject
表示key-value结构的数据类型,如:
{
name: 'hanmeimei',
age: '17',
date: '1999-02-02'
}
AKI
支持使用C/C 的std::map<std::string, T>
映射JavaScript的JsonObject
。
- 与
std::map<std::string, T>
对应的JsonObject
必须约束value类型一致 - Example
- C
void Foo(std::map<std::string, int> obj)
{
for (auto& iter : obj) {
......; // key: iter.first; value: iter.second
}
}
JSBIND_GLOBAL() {
JSBIND_FUNCTION(Foo);
}
- JavaScript
import libmap_for_object from 'libmap_for_object.so'
let a = {age: 100};
libmap_for_object.Foo(a);
Function
Function是JS的一种基本数据类型,当JS传入Function作为参数时,Native可在适当的时机调用触发回调。AKI
支持如下3中C 数据类型作为参数处理回调:
- aki::Callback<R (P...)>:指定回调类型为
R (*)(P...)
的高性能回调。非线程安全,禁止在非JS线程使用,否则会发生异常; - aki::SafetyCallback<R (P...)>:指定回调类型为
R (*)(P...)
的线程安全回调。因为需要创建线程安全资源,所以性能不如aki::Callback; - std::function<R (P...)>:用法与aki::SafetyCallback一致;
对象引用&指针
C 对象作为参数和返回类型,在 C & JavaScript 代码中可以使用如下形式进行传递:
- 值传递;
- 引用(T&)与指针(T*)传递;
API参考
napi_env 获取
代码语言:c复制static napi_env aki::JSBind::GetScopedEnv();
线程安全函数,用于获取当前线程的 napi_env 对象。当在非 JS 线程调用时,返回 nullptr。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | Y | 需要读取的属性名。 |
示例:
代码语言:c复制// 在 JS 线程执行
napi_value obj;
napi_env env = aki::JSBind::GetScopedEnv();
napi_create_object(env, &obj);
TaskRunner 任务调度器
TaskRunner
提供JS线程的任务调度器,开发人员可以很方便地往JS线程PostTask
JSBind.initTaskRunner(name: string)
JS
侧的静态函数,用于初始化对应JS线程的任务调度器。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
runnerName | string | Y | 任务调度器别名。 |
示例:
代码语言:js复制import libAddon from "libaki.so"
libAddon.JSBind.initTaskRunner("name");
PostTask
代码语言:c复制static void PostTask(const std::string& runnerName, Closure task);
静态函数,往指定任务调度器,投递任务。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
runnerName | string | Y | 指定任务调度器,需先使用 |
task | Closure | Y | 任务表达式: std::function<void ()>。 |
示例:
代码语言:c复制void foo ()
{
aki::TaskRunner::PostTask("main", [] () {
// 在 JS 线程执行
// do something
});
}
aki::Value <sup> v1.2.0 </sup>
JavaScript 是弱类型语言,可用泛型any
表示任意类型。C/C 使用aki::Value
映射 JavaScript 的any
类型
aki::Value::FromGlobal
代码语言:c复制static Value FromGlobal(const char* key = nullptr)
用于获取 JS 侧globalThis
下的属性。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | Y | 需要读取的属性名。 |
返回值:
类型 | 说明 |
---|---|
aki::Value | 对应属性的 JS 对象句柄。 |
示例:
代码语言:c复制 // 获取globalThis.JSON
aki::Value json = aki::Value::FromGlobal("JSON");
json["stringify"](obj);
aki::Value::As
代码语言:c复制template<typename T>
T As() const;
模板函数,用于将 JS 对象转化为 C/C 指定数据类型
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
T | any | Y | 需要被转化的 C/C 数据类型。 |
返回值:
类型 | 说明 |
---|---|
T | 对应类型的值。 |
示例:
代码语言:c复制 value.As<bool>(); // 将 JS 对象 value 转化为 bool
value.As<int>(); // 将 JS 对象 value 转化为 int
value.As<std::string>(); // 将 JS 对象 value 转化为 string
aki::Value::GetHandle
代码语言:c复制napi_value GetHandle() const
用于获取 JS 对象的 napi_value 句柄。
返回值:
类型 | 说明 |
---|---|
napi_value | JS 对象的 napi_value 句柄。 |
aki::Value::CallMethod
代码语言:c复制template<typename... Args>
Value CallMethod(const char* name, Args&&... args)
调用 JS 对象的成员函数。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
name | string | Y | 函数名。 |
args | any | N | 成员函数接收的参数。 |
返回值:
类型 | 说明 |
---|---|
aki::Value | 返回泛型对象。 |
示例:
代码语言:c复制 // value 映射为 JS 数组对象 let value = ['aki'];
// 调用 value.push('jsbind');
value.CallMethod("push", "jsbind");
aki::Value::operator[]
代码语言:c复制Value operator[](const std::string& key) const;
Value operator[](const size_t index) const;
aki::Value
对象的下标运算符
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | Y | 属性名下标。 |
index | size_t | Y | 数组下标。 |
返回值:
类型 | 说明 |
---|---|
aki::Value | 返回泛型对象。 |
示例:
代码语言:c复制 // value 映射为 JS 数组对象 let value = ['aki', 'jsbind'];
// 访问下标为0的值:'aki';
aki::Value str = value[0]; // str = "aki"
// 调用 JSON.stringify(...);
aki::Value::FromGlobal("JSON")["stringify"](...);
aki::Value::operator()
代码语言:c复制template<typename... Args>
Value operator()(Args&&... args) const;
aki::Value
对象的函数调用运算符
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
args | any | N | 函数所接收入参。 |
返回值:
类型 | 说明 |
---|---|
aki::Value | 返回泛型对象。 |
示例:
代码语言:c复制 // 调用 JSON.parse({'aki': 'jsinbd'});
aki::Value::FromGlobal("JSON")["parse"]({"aki": "jsinbd"});
aki::Value::Set
代码语言:c复制template<typename V>
void Set(const char* key, const V& value);
用于给aki::Value
泛型对象属性设值。
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
key | string | Y | 属性名。 |
value | any | Y | 属性值。 |
示例:
代码语言:c复制 // value 为 JS 对象;
value.Set("name", "aki");
aki::Value::NewObject
代码语言:c复制static Value NewObject();
创建aki::Value
泛型对象。
返回值:
类型 | 说明 |
---|---|
aki::Value | 返回泛型对象。 |
示例:
代码语言:c复制 aki::Value val = aki::Value::NewObject();
val.Set("name", "aki"); // {'name': 'aki'};
aki::Value::IsUndefined
代码语言:c复制bool IsUndefined() const
判断 JS 对象类型是否为undefined
。
返回值:
类型 | 说明 |
---|---|
bool | true or false。 |
aki::Value::IsNull
代码语言:c复制bool IsNull() const
判断 JS 对象类型是否为null
。
返回值:
类型 | 说明 |
---|---|
bool | true or false。 |
aki::Value::IsBool
代码语言:c复制bool IsBool() const
判断 JS 对象类型是否为boolean
。
返回值:
类型 | 说明 |
---|---|
bool | true or false。 |
aki::Value::IsNumber
代码语言:c复制bool IsNumber() const
判断 JS 对象类型是否为number
。
返回值:
类型 | 说明 |
---|---|
bool | true or false。 |
aki::Value::IsString
代码语言:c复制bool IsString() const
判断 JS 对象类型是否为string
。
返回值:
类型 | 说明 |
---|---|
bool | true or false。 |
aki::Value::IsArray
代码语言:c复制bool IsArray() const
判断 JS 对象类型是否为数组[]
。
返回值:
类型 | 说明 |
---|---|
bool | true or false。 |
aki::Value::IsFunction
代码语言:c复制bool IsFunction() const
判断 JS 对象类型是否为function
。
返回值:
类型 | 说明 |
---|---|
bool | true or false。 |
C/C 调用 @ohos.bundle.bundleManager (bundleManager模块)特性
示例:
- 期望在 C 调用如下@ohos.bundle.bundleManager (bundleManager模块) 特性:
import bundleManager from '@ohos.bundle.bundleManager';
import hilog from '@ohos.hilog';
let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT;
try {
bundleManager.getBundleInfoForSelf(bundleFlags).then((data) => {
hilog.info(0x0000, 'testTag', 'getBundleInfoForSelf successfully. Data: %{public}s', JSON.stringify(data));
}).catch(err => {
hilog.error(0x0000, 'testTag', 'getBundleInfoForSelf failed. Cause: %{public}s', err.message);
});
} catch (err) {
hilog.error(0x0000, 'testTag', 'getBundleInfoForSelf failed: %{public}s', err.message);
}
使用如下C
代码实现上述功能
/* 要求在ArkTS侧执行如下代码:
* import bundleManager from '@ohos.bundle.bundleManager';
* globalThis.bundleManager = bundleManager;
*/
aki::Value bundleManager = aki::Value::FromGlobal("bundleManager");
/* 如下 C 代码等同于 JS 代码:
* let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT;
* bundleManager.getBundleInfoForSelf(bundleFlags).then((data) => {
* console.log('getBundleInfoForSelf successfully. Data:', JSON.stringify(data));
* })
*/
std::function<void(aki::Value)> thenFunc = [](aki::Value data) {
AKI_LOG(INFO) << aki::Value::FromGlobal("JSON")["stringify"](data).As<std::string>();
};
int bundleFlags = bundleManager["BundleFlag"]["GET_BUNDLE_INFO_DEFAULT"].As<int>();
bundleManager["getBundleInfoForSelf"](bundleFlags).CallMethod("then", thenFunc);
aki::ArrayBuffer
constructor
- 当在非 JS 线程使用 aki::ArrayBuffer,需要关注数据字节流生命周期,并考虑是否需要结合
Commit()
函数使用。
ArrayBuffer(uint8_t* ptr, size_t len, Typed typed = BUFF)
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
ptr | uint8_t* | Y | 构造 ArrayBuffer 的数据字节流内存地址。 |
len | size_t | Y | 构造 ArrayBuffer 的数据字节流内存长度。 |
typed | aki::ArrayBuffer::Typed | N | 构造的 ArrayBuffer | TypedArray 类型,默认为 ArrayBuffer。 |
示例:
代码语言:c复制uint8_t temp[4] = {10, 20, 30, 40};
aki::ArrayBuffer arrayBuffer(temp, 4);
GetData
代码语言:c复制uint8_t* GetData()
获取 ArrayBuffer 的数据字节流内存地址。
返回值:
类型 | 说明 |
---|---|
uint8_t* | ArrayBuffer 的数据字节流内存地址。 |
GetLength
代码语言:c复制size_t GetLength()
获取 ArrayBuffer 的数据字节流内存长度。
返回值:
类型 | 说明 |
---|---|
size_t | ArrayBuffer 的数据字节流内存长度。 |
Commit
代码语言:c复制void Commit()
当在非 JS 线程使用 ArrayBuffer 时,如果数据字节流的内存生命周期在 ArrayBuffer 使用前结束,则需要暂存。
返回值:
类型 | 说明 |
---|---|
size_t | ArrayBuffer 的数据字节流内存长度。 |
示例:
代码语言:c复制// 非 JS 线程
aki::ArrayBuffer AsyncTaskReturnArrayBufferWithCommit() {
uint8_t temp[4] = {10, 20, 30, 40};
aki::ArrayBuffer arrayBuffer(temp, 4);
arrayBuffer.Commit();
return arrayBuffer;
}
AKI hybrid Node-API 混合开发
AKI
支持与 Node-API 混合开发。接口 aki::JSBind::BindSymbols
用于绑定使用 AKI
的 Native 符号表给指定的 napi_value 对象。
如下示例:
examples/ohos/4_hybrid_napi/entry/src/main/hello.cpp
代码语言:c复制EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
...
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
exports = aki::JSBind::BindSymbols(env, exports); // aki::JSBind::BindSymbols 函数传入 js 对象绑定符号
return exports;
}
EXTERN_C_END
Benchmark
- IDE: DevEco Studio 3.1.1.130
- SDK:3.2.10.6
API接口压测,当前采用了OHOS上单元测试框架的数据驱动能力,详见benchmark