使用Node-API进行同步任务开发

2024-09-07 11:12

本文主要是介绍使用Node-API进行同步任务开发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        在同步任务开发中,ArkTS应用侧主线程将阻塞等待Native侧计算结果,Native侧计算结果通过方舟引擎反馈给ArkTS应用侧。此过程中,Native接口代码与ArkTS应用侧均运行在ArkTS主线程上。为了Native侧业务处理具有同步效果,案例中的生产者与消费者线程则采用join()的方式来进行同步处理。

        同步调用也支持带Callback,具体方式由应用开发者决定,通过是否传递Callback函数进行区分。

        从上图中,可以看出,当Native同步任务接口被调用时,该接口会完成参数解析、数据类型转换、创建生产者和消费者线程等。在等待生产者线程和消费者线程执行结束后,将图片路径结果转换为napi_value,由方舟引擎直接反馈到ArkTS应用侧。

一、同步任务开发步骤(简介)       

        1、ArkTS应用侧开发

// Index.ets文件// 导入libentry.so库,返回ArkTS对象testNapi 
import testNapi from 'libentry.so';
import Constants from '../../common/constants/CommonConstants';@Entry
@Component
struct Index {build() {Column() {...Column() {...Button($r('app.string.sync_button_title'))....onClick(() => {// 通过testNapi,传入callback回调,调用Native接口,进行业务计算testNapi.addSyncCallback(2,3,(nativeResult: number) => {this.result = nativeResult;})...}...}...}
}

        2、Native侧开发 

// index.d.ts文件// ArkTS侧的Native接口声明
export const addSyncCallback: (a: number, b: number,callback: (nativeResult: number) => void) => void;
static napi_value AddSyncCallback(napi_env env,napi_callback_info info) {...// 解析ArkTS应用侧传入参数napi_get_cb_info(env, info, &argc, args, &context, nullptr);// 将参数从napi_value类型转换为double类型double value0;napi_get_value_double(env, args[0], &value0);double value1;napi_get_value_double(env, args[1], &value1);napi_value callBackArg = nullptr;// 业务处理,两数相加,将结果返回napi_valuenapi_create_double(env, add(value0, value1), &callBackArg);napi_value res = nullptr;// 通过回调返回结果到应用napi_call_function(env, context, args[2], 1, callBackArg, &res);return res;
}

二、同步任务开发步骤(实例)

        1、ArkTS应用侧开发

import testNapi from 'libentry.so';
import Constants from '../../common/constants/CommonConstants';@Entry
@Component
struct Index {@State imagePath: string = Constants.INIT_IMAGE_PATH;imageName: string = '';build() {Column() {...// button list, prompting the user to click the button to select the target image.Column() {...// multi-threads sync call buttonButton($r('app.string.sync_button_title')).width(Constants.FULL_PARENT).margin($r('app.float.button_common_margin')).onClick(() => {this.imageName = Constants.SYNC_BUTTON_IMAGE;this.imagePath = Constants.IMAGE_ROOT_PATH + testNapi.getImagePathSync(this.imageName);})...}...}...}
}

        2、Native侧开发

        在同步任务开发中,Native侧接口原生代码仍然运行在ArkTS主线程上。

        导出Native接口:将Native接口导出到ArkTS侧,用于支撑ArkTS对象调用和模块编译构建。

// export sync interface
export const getImagePathSync: (imageName: string) => string;

        上下文数据结构定义:用于任务执行过程中,上下文数据存储。后文异步任务开发和线程安全开发中实现相同,后续不再赘述。

// context data provided by users
// data is transferred between the native method (initialization data), ExecuteFunc, and CompleteFunc
struct ContextData {napi_async_work asyncWork = nullptr; // async work objectnapi_deferred deferred = nullptr;    // associated object of the delay object promisenapi_ref callbackRef = nullptr;      // reference of callbackstring args = "";                    // parameters from ArkTS --- imageNamestring result = "";                  // C++ sub-thread calculation result --- imagePath
};

        销毁上下文数据:在任务执行结束或者失败后,需要销毁上下文数据进行内存释放。后文异步任务开发和线程安全开发中实现相同,后续不再赘述。

// MultiThreads.cpp文件static void DeleteContext(napi_env env, ContextData *contextData) {// delete callback referenceif (contextData->callbackRef != nullptr) {(void)napi_delete_reference(env, contextData->callbackRef);}// delete async workif (contextData->asyncWork != nullptr) {(void)napi_delete_async_work(env, contextData->asyncWork);}// release context datadelete contextData;
}

        Native同步任务开发接口:解析ArkTS应用侧参数、数据类型转换、创建生产者和消费者线程,并使用join()进行同步处理。最后在获取结果后,将数据转换为napi_value类型,返回给ArkTS应用侧。

// MultiThreads.cpp文件
// sync interface
static napi_value GetImagePathSync(napi_env env, napi_callback_info info) {size_t paraNum = 1;napi_value paraArray[1] = {nullptr};// parse parametersnapi_status operStatus = napi_get_cb_info(env, info, &paraNum, paraArray, nullptr, nullptr);if (operStatus != napi_ok) {return nullptr;}napi_valuetype paraDataType = napi_undefined;operStatus = napi_typeof(env, paraArray[0], &paraDataType);if ((operStatus != napi_ok) || (paraDataType != napi_string)) {return nullptr;}// convert napi_value to char *constexpr size_t buffSize = 100;char strBuff[buffSize]{}; // char buffer for imageName stringsize_t strLength = 0;operStatus = napi_get_value_string_utf8(env, paraArray[0], strBuff, buffSize, &strLength);if ((operStatus != napi_ok) || (strLength == 0)) {return nullptr;}// defines context data. the memory will be released in CompleteFuncauto contextData = new ContextData;contextData->args = strBuff;// create producer threadthread producer(ProductElement, static_cast<void *>(contextData));producer.join();// create consumer threadthread consumer(ConsumeElement, static_cast<void *>(contextData));consumer.join();// convert the result to napi_value and send it to ArkTs applicationnapi_value result = nullptr;(void)napi_create_string_utf8(env, contextData->result.c_str(), contextData->result.length(), &result);// delete context dataDeleteContext(env, contextData);return result;
}

这篇关于使用Node-API进行同步任务开发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java中的ConcurrentBitSet使用小结

《Java中的ConcurrentBitSet使用小结》本文主要介绍了Java中的ConcurrentBitSet使用小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、核心澄清:Java标准库无内置ConcurrentBitSet二、推荐方案:Eclipse

Go语言结构体标签(Tag)的使用小结

《Go语言结构体标签(Tag)的使用小结》结构体标签Tag是Go语言中附加在结构体字段后的元数据字符串,用于提供额外的属性信息,这些信息可以通过反射在运行时读取和解析,下面就来详细的介绍一下Tag的使... 目录什么是结构体标签?基本语法常见的标签用途1.jsON 序列化/反序列化(最常用)2.数据库操作(

Java中ScopeValue的使用小结

《Java中ScopeValue的使用小结》Java21引入的ScopedValue是一种作用域内共享不可变数据的预览API,本文就来详细介绍一下Java中ScopeValue的使用小结,感兴趣的可以... 目录一、Java ScopedValue(作用域值)详解1. 定义与背景2. 核心特性3. 使用方法

spring中Interceptor的使用小结

《spring中Interceptor的使用小结》SpringInterceptor是SpringMVC提供的一种机制,用于在请求处理的不同阶段插入自定义逻辑,通过实现HandlerIntercept... 目录一、Interceptor 的核心概念二、Interceptor 的创建与配置三、拦截器的执行顺

Python在二进制文件中进行数据搜索的实战指南

《Python在二进制文件中进行数据搜索的实战指南》在二进制文件中搜索特定数据是编程中常见的任务,尤其在日志分析、程序调试和二进制数据处理中尤为重要,下面我们就来看看如何使用Python实现这一功能吧... 目录简介1. 二进制文件搜索概述2. python二进制模式文件读取(rb)2.1 二进制模式与文本

SQL Server 中的表进行行转列场景示例

《SQLServer中的表进行行转列场景示例》本文详细介绍了SQLServer行转列(Pivot)的三种常用写法,包括固定列名、条件聚合和动态列名,文章还提供了实际示例、动态列数处理、性能优化建议... 目录一、常见场景示例二、写法 1:PIVOT(固定列名)三、写法 2:条件聚合(CASE WHEN)四、

C#中checked关键字的使用小结

《C#中checked关键字的使用小结》本文主要介绍了C#中checked关键字的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录✅ 为什么需要checked? 问题:整数溢出是“静默China编程”的(默认)checked的三种用

C#中预处理器指令的使用小结

《C#中预处理器指令的使用小结》本文主要介绍了C#中预处理器指令的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录 第 1 名:#if/#else/#elif/#endif✅用途:条件编译(绝对最常用!) 典型场景: 示例

SpringBoo WebFlux+MongoDB实现非阻塞API过程

《SpringBooWebFlux+MongoDB实现非阻塞API过程》本文介绍了如何使用SpringBootWebFlux和MongoDB实现非阻塞API,通过响应式编程提高系统的吞吐量和响应性能... 目录一、引言二、响应式编程基础2.1 响应式编程概念2.2 响应式编程的优势2.3 响应式编程相关技术

java中4种API参数传递方式统一说明

《java中4种API参数传递方式统一说明》在Java中,我们可以使用不同的方式来传递参数给方法或函数,:本文主要介绍java中4种API参数传递方式的相关资料,文中通过代码介绍的非常详细,需要的... 目录1. 概述2. 参数传递方式分类2.1 Query Parameters(查询参数)2.2 Path