使用Node-API实现跨语言交互开发流程

2024-09-06 17:28

本文主要是介绍使用Node-API实现跨语言交互开发流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、前言

        使用Node-API实现跨语言交互,首先需要按照Node-API的机制实现模块的注册和加载等相关动作。

  • ArkTS/JS侧:实现C++方法的调用。代码比较简单,import一个对应的so库后,即可调用C++方法。

  • Native侧:.cpp文件,实现模块的注册。需要提供注册lib库的名称,并在注册回调方法中定义接口的映射关系,即Native方法及对应的JS/ArkTS接口名称等。

        此处以在ArkTS/JS侧实现add()接口、在Native侧实现Add()接口,从而实现跨语言交互为例,呈现使用Node-API进行跨语言交互的流程。

二、创建Native C++工程

  • 在DevEco Studio中New > Create Project,选择Native C++模板,点击Next,选择API版本,设置好工程名称,点击Finish,创建得到新工程。

  • 创建工程后工程结构可以分两部分,cpp部分和ets部分。工程结构如下:

         

三、Native侧方法的实现

        1、设置模块注册信息

        ArkTS侧import native模块时,会加载其对应的so。加载so时,首先会调用napi_module_register方法,将模块注册到系统中,并调用模块初始化函数。

        napi_module有两个关键属性:一个是.nm_register_func,定义模块初始化函数;另一个是.nm_modname,定义模块的名称,也就是ArkTS侧引入的so库的名称,模块系统会根据此名称来区分不同的so。

// entry/src/main/cpp/hello.cpp// 准备模块加载相关信息,将上述Init函数与本模块名等信息记录下来。
static napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "entry",.nm_priv = nullptr,.reserved = {0},
};// 加载so时,该函数会自动被调用,将上述demoModule模块注册到系统中。
extern "C" __attribute__((constructor)) void RegisterDemoModule() { napi_module_register(&demoModule);}

        2、模块初始化

        实现ArkTS接口与C++接口的绑定和映射。

// entry/src/main/cpp/hello.cpp
EXTERN_C_START
// 模块初始化
static napi_value Init(napi_env env, napi_value exports) {// ArkTS接口与C++接口的绑定和映射napi_property_descriptor desc[] = {{"callNative", nullptr, CallNative, nullptr, nullptr, nullptr, napi_default, nullptr},{"nativeCallArkTS", nullptr, NativeCallArkTS, nullptr, nullptr, nullptr, napi_default, nullptr},};// 在exports对象上挂载CallNative/NativeCallArkTS两个Native方法napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_END// 模块基本信息
static napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "entry",.nm_priv = nullptr,.reserved = {0},
};

        3、在index.d.ts文件中,提供JS侧的接口方法

// entry/src/main/cpp/types/libentry/index.d.ts
export const callNative: (a: number, b: number) => number;
export const nativeCallArkTS: (cb: (a: number) => number) => number;

        4、在oh-package.json5文件中将index.d.ts与cpp文件关联起来

{"name": "libentry.so","types": "./index.d.ts","version": "","description": "Please describe the basic information."
}

        5、在CMakeLists.txt文件中配置CMake打包参数

# entry/src/main/cpp/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
project(MyApplication2)set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include)# 添加名为entry的库
add_library(entry SHARED hello.cpp)
# 构建此可执行文件需要链接的库
target_link_libraries(entry PUBLIC libace_napi.z.so)

        6、实现Native侧的CallNative以及NativeCallArkTS接口

// entry/src/main/cpp/hello.cpp
static napi_value CallNative(napi_env env, napi_callback_info info)
{size_t argc = 2;// 声明参数数组napi_value args[2] = {nullptr};// 获取传入的参数并依次放入参数数组中napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);// 依次获取参数double value0;napi_get_value_double(env, args[0], &value0);double value1;napi_get_value_double(env, args[1], &value1);// 返回两数相加的结果napi_value sum;napi_create_double(env, value0 + value1, &sum);return sum;
}static napi_value NativeCallArkTS(napi_env env, napi_callback_info info)
{    size_t argc = 1;// 声明参数数组napi_value args[1] = {nullptr};// 获取传入的参数并依次放入参数数组中napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);// 创建一个int,作为ArkTS的入参napi_value argv = nullptr;    napi_create_int32(env, 2, &argv );// 调用传入的callback,并将其结果返回napi_value result = nullptr;napi_call_function(env, nullptr, args[0], 1, &argv, &result);return result;
}

四、ArkTS侧调用C/C++方法实现

        ArkTS侧通过import引入Native侧包含处理逻辑的so来使用C/C++的方法。

// entry/src/main/ets/pages/Index.ets
// 通过import的方式,引入Native能力。
import nativeModule from 'libentry.so'@Entry
@Component
struct Index {@State message: string = 'Test Node-API callNative result: ';@State message2: string = 'Test Node-API nativeCallArkTS result: ';build() {Row() {Column() {// 第一个按钮,调用add方法,对应到Native侧的CallNative方法,进行两数相加。Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.message += nativeModule.callNative(2, 3);})// 第二个按钮,调用nativeCallArkTS方法,对应到Native的NativeCallArkTS,在Native调用ArkTS function。Text(this.message2).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.message2 += nativeModule.nativeCallArkTS((a: number)=> {return a * 2;});})}.width('100%')}.height('100%')}
}

五、Node-API的约束限制

        1、SO命名规则

        导入使用的模块名和注册时的模块名大小写保持一致,如模块名为entry,则so的名字为libentry.so,napi_module中nm_modname字段应为entry,ArkTS侧使用时写作:import xxx from 'libentry.so'。

        2、注册建议

  • nm_register_func对应的函数(如上述Init函数)需要加上static,防止与其他so里的符号冲突;

  • 模块注册的入口,即使用__attribute__((constructor))修饰的函数的函数名(如上述RegisterDemoModule函数)需要确保不与其它模块重复。

        3、多线程限制

        每个引擎实例对应一个JS线程,实例上的对象不能跨线程操作,否则会引起应用crash。使用时需要遵循如下原则:

  • Node-API接口只能在JS线程使用。

  • Native接口入参env与特定JS线程绑定只能在创建时的线程使用。

这篇关于使用Node-API实现跨语言交互开发流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1142646

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传