【OpenHarmony-NDK技术】简单将cJson移植到OpenHarmony中,并在c层修改参数值再返回json

1、cJson的简单介绍

cJson - github网址

概述

一般使用cJson是,需要将json文本转化为json对象–编码,将json对象转化为json文本–解析。
git clone https://github.com/DaveGamble/cJSON.git
后留意cJSON.h和cJSON.h两个文件。

1、cJson的介绍
cJson是一个数据结构,里面含有prev next child 等指针用于获取json数据的具体值
typedef struct cJSON
{   struct cJSON *next;struct cJSON *prev;struct cJSON *child;//type是指,该节点的数据类型 int type;//字符串获取的变量char *valuestring;//int值获取的变量int valueint;//double 值获取的变量double valuedouble;//暂未接触char *string;
} cJSON;//int type的值,去这几种
//#define cJSON_Invalid (0)
//#define cJSON_False  (1 << 0)
//#define cJSON_True   (1 << 1)
//#define cJSON_NULL   (1 << 2)
//#define cJSON_Number (1 << 3)
//#define cJSON_String (1 << 4)
//#define cJSON_Array  (1 << 5)
//#define cJSON_Object (1 << 6)
//#define cJSON_Raw    (1 << 7)//编码方法
cJson* cJSON_Parse(char *); 
//解码方法
char* cJSON_Print(cJson *); 
2、编码
//1、声明一个简单的字符串
char *jsonText = "{\"name\":\"zhangsan\",\"age\":18,\"price\":21.0}";
//2、将字符串给到cJSON_Parse方法,json!=null,就会给到一个cJson结构。
cJSON *json = cJSON_Parse(jsonText);// 获取到string的值
json->valuestring
// 获取到string的值
json->valuestring
// 获取到int的值
json->valueint
// 获取到int的值
json->valuedouble//以上三种方法获取对应类型的字段的值// 3、通过根json去获取到具体的一个字段(name)
cJSON *jsonValue = cJSON_GetObjectItem(json, "name");
//返回的也是一个cJson结构,获取值与上面相同操作 
3、解码
//1.将一个cJOSN的结构,变量一个json文本
char * cJSON_Print(cJSON *);

2、OpenHarmony项目实现

1、项目创建

IDE版本:
DevEco Studio 3.1.1 Release
Build Version: 3.1.0.501, built on June 20, 2023
Build #DS-223.8617.56.36.310501
Runtime version: 17.0.6+10-b829.5 amd64

按照官方的要求创建一个Native项目

2、目录及文件介绍

在这里插入图片描述

1、cJSON.c是cjson实现的源码
2、cJSON.h是cJSON.c的头文件,以上两个文件可以在上面git中获取。
3、CMakeList.exe 文件时配置cmake编译的配置文件
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(MyFirstCpp)# 定义一个变量,并赋值为当前模块cpp目录
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})# 添加头文件.h目录,包括cpp,cpp/include,告诉cmake去这里找到代码引入的头文件
include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include)
# hiloglib -- 给c层打印日志使用的
find_library(hilog_libhilog_ndk.z
)
# 声明一个产物libentry.so,SHARED表示产物为动态库,hello.cpp为产物的源代码
# !!!注意:如果使用源码一起编译是,需要将源文件添加进来,例如:hello.cpp cjson.c
add_library(entry SHARED hello.cpp cjson.c)# 声明产物entry链接时需要的三方库libace_napi.z.so
# 这里直接写三方库的名称是因为它是在ndk中,已在链接寻址路径中,无需额外声明
# 添加的编译so库
target_link_libraries(entry PUBLIC ${hilog_lib} libace_napi.z.so)
4、Index.ets 布局文件
//伪代码
import testNapi from 'libentry.so'
json: string = "{\"name\":\"zhangsan\",\"age\":18,\"price\":21.5}";
Button().onClick(() => {let json = testNapi.modifyJson(this.json,this.inputText);hilog.info(0x0000, 'testTag', 'cjson name = %{public}d', json);
}
5、LogUtils.ts 是一个打印日志的工具
export class LogUtils{static Tag:string = 'MyFirstCpp';static i(...args){hilog.info(0x0000, LogUtils.Tag, '%{public}s', args);}static d(msg:string){hilog.debug(0x0000, LogUtils.Tag, '%{public}s', msg);}static e(msg:string){hilog.error(0x0000, LogUtils.Tag, '%{public}s', msg);}
}
6、hello.cpp文件方法配置介绍

初始化创建一个Native 项目在hello.cpp文件中默认存在如下代码:

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {napi_property_descriptor desc[] = {{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},//{"modifyJson", nullptr, ModifyJson, nullptr, nullptr, nullptr, napi_default, nullptr},};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_ENDstatic napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "entry",.nm_priv = ((void *)0),.reserved = {0},
};extern "C" __attribute__((constructor)) void RegisterEntryModule(void) {napi_module_register(&demoModule);
}

其中 napi_property_descriptor 变量里面存在的是c对应js的方法。需要添加不同的方法(js调用的方法)需要在这里声明。
{“add”, nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}
目前按照以上格式,替换一下【“add”】 和 【Add】的值。
eg:
我现在要声明一个modifyJson方法,如下参数,js层也一并需要声明。

{"modifyJson", nullptr, ModifyJson, nullptr, nullptr, nullptr, napi_default, nullptr}

在js层也需要声明条用的方法如下:
在src/main/cpp/types/libentry/index.d.ts文件下:

export const add: (a: number, b: number) => number;

eg:
添加 modifyJson 方法

export const add: (a: number, b: number) => number;
//json 是json字符串;nameValue 是修改name字段的值 
export const modifyJson:(json:string,nameValue:string)=>string;
3、代码介绍

首先NDK开发使用的是js的napi库。需要注意的是js和C/C++之间的数据类型之间的切换。

1、napi与C/C++之间数据类型切换

anpi 中的数据目前使用一个napi_value (js层接收的类型)
C/C++中的数据类型目前用到了 string,char*,int, double

下面就是 anpi_value 转为 C/C++ string、int、double

/*** 获取 js中的string 到 C中使用* @param env* @param value* @return */
static const string get_native_string_value(napi_env env,napi_value value){//不知道字符串长度,先获取一下,拿到字符串的真实长度size_t textLen;napi_get_value_string_utf8(env, value, NULL, 0, &textLen);//得到了真实的长度,需要在次长度上+1(不全\0)char text[textLen+1];napi_get_value_string_utf8(env, value,text, sizeof(text), &textLen);//返回的是std:string,记得导入 using namespace std;string buf(text, textLen);return buf;}/*** 获取 js 中的 int 到 C中使用* @param env* @param _msg* @return */
static int get_native_int_value(napi_env env,napi_value value){int32_t iNum;napi_get_value_int32(env, value, &iNum);return iNum;
}/*** 获取 js 中的double 到C中使用* @param env* @param _msg* @return */
static double get_native_double_value(napi_env env,napi_value value){double dNum;napi_get_value_double(env, value, &dNum);return dNum;
}

下面就是 C/C++ string、int、double 转为 napi_value(可以直接返回给js层的类型)

/*** 将c中的char* 构建一个 js的string类型* @return */
static napi_value return_string_value(napi_env env,char *_msg){napi_value msg;napi_create_string_utf8(env, _msg, strlen(_msg), &msg);return msg;
}/*** 将c中的int 构建一个 js的int类型* @return */
static napi_value return_int_value(napi_env env,int _msg){napi_value i;napi_create_int32(env, _msg, &i);return i;
}/*** 将c中的double 构建一个 js的double类型* @return */
static napi_value return_double_value(napi_env env,double _msg){napi_value d;napi_create_double(env, _msg, &d);return d;
}
4、核心处理
static napi_value ModifyJson(napi_env env, napi_callback_info info) {napi_value modifyJson;// OH_LOG_INFO c的日志,需要按照CmakeList.txt 导入库。不然无法访问OH_LOG_INFO(LOG_APP,"ModifyJson start");//1、获取js中传过来的参数,放入 args 数组中,argc 是有两个参数size_t argc = 2;napi_value args[2] = {nullptr};napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);//2.获取对应参数的值string jsonText = get_native_string_value(env, args[0]);//3.获取修改的文本string newName = get_native_string_value(env, args[1]);//4.编码jsoncJSON *jsonObj = cJSON_Parse(jsonText.c_str());//5.获取字段为 name 的json对象,然后操作这个对象获取值和修改值cJSON *nameValueObj = cJSON_GetObjectItemCaseSensitive(jsonObj, "name");if(NULL == nameValueObj){//Undefined_value 和 get_native_string_value,类似只是返回 char* -> napi_value return Undefined_value(env, "NULL == nameValueObj");}//6.修改 nameValueObj 值,注意:赋值要使用 strdup 方法进行包一层,不然在 cJSON_Delete 释放时会报错//之前一个是将char* 赋值到valuestring 中,不进行strdup释放的时候回报错
//    nameValueObj->valuestring = strdup(newName.c_str());//查看cjson源码发现,自带一个修改指定字段的值 cJSON_SetValuestringcJSON_SetValuestring(nameValueObj, newName.c_str());//7.修改完值后需要重新进行对 jsonObj 进行 解码 json 再返回json到js层char *newJson = cJSON_Print(jsonObj);//8、返回新的json字符串napi_create_string_utf8(env, newJson, strlen(newJson), &modifyJson);//释放 jsonObjcJSON_Delete(jsonObj);return modifyJson;
}

以上就是简单的将cJson 移植到OpenHarmony。希望可以帮助到大家!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/1513.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang那些违背直觉的编程陷阱

目录 知识点1&#xff1a;切片拷贝之后都是同一个元素 知识点2&#xff1a;方法集合决定接口实现&#xff0c;类型方法集合是接口方法集合的超集则认定为实现接口&#xff0c;否则未实现接口 切片拷贝之后都是同一个元素 package mainimport ("encoding/json"&quo…

Redis 如何实现分布式锁

课程地址 单机 Redis naive 版 加锁&#xff1a; SETNX ${lockName} ${value} # set if not exist如果不存在则插入成功&#xff0c;返回 1&#xff0c;加锁成功&#xff1b;否则返回 0&#xff0c;加锁失败 解锁&#xff1a; DEL ${lockName}问题1 2 个线程 A、B&#…

前后端交互概念

前后端交互概念 1前后端分离开发概念2搭建后端环境2.1配置文件commomcommon-utilservice-utilmodelservice gitee使用 1前后端分离开发概念 前段&#xff1a;运用html、css、js和现成库&#xff0c;对数据作展示。 后端&#xff1a;运用Java和Java框架&#xff0c;提供数据或操…

立创·实战派ESP32-C3开发板 with lv_micropython

一、lv_micropython对驱动芯片的支持 ESP32-C3开发板的Display drivers:ST7789&#xff0c;Input drivers:FT6336&#xff0c;从LVGL的官方文档了解到lv_micropython包含了这两颗IC的驱动。 参考文档&#xff1a; lv_micropython already contains these drivers: 链接:Micro…

智慧化转型赋能园区创新:科技创新引领产业智慧化,打造高效发展新格局

在全球化和信息化浪潮的推动下&#xff0c;园区作为区域经济发展的重要引擎&#xff0c;正面临着前所未有的机遇与挑战。为应对这些挑战并把握机遇&#xff0c;园区需积极拥抱智慧化转型&#xff0c;通过科技创新引领产业智慧化&#xff0c;打造高效发展的新格局。本文将深入探…

贝叶斯分类 python

贝叶斯分类 python 贝叶斯分类器是一种基于贝叶斯定理的分类方法&#xff0c;常用于文本分类、垃圾邮件过滤等领域。 在Python中&#xff0c;我们可以使用scikit-learn库来实现贝叶斯分类器。 下面是一个使用Gaussian Naive Bayes(高斯朴素贝叶斯)分类器的简单示例&#xff1…

go | defer、panic、recover

刷一道题&#xff0c; 将当函数触发panic 之后&#xff0c;函数是怎么执行的 然后我去找相关博客&#xff0c;发现这篇讲的蛮好的 接下来我直接上demo &#xff0c;然后通过demo 来逐个分析 package mainimport ("fmt" )func f() {defer func() {if r : recover();…

毕业设计——基于ESP32的智能家居系统(语音识别、APP控制)

ESP32嵌入式单片机实战项目 一、功能演示二、项目介绍1、功能演示2、外设介绍 三、资料获取 一、功能演示 多种控制方式 ① 语音控制 ②APP控制 ③本地按键控制 ESP32嵌入式单片机实战项目演示 二、项目介绍 1、功能演示 这一个基于esp32c3的智能家居控制系统&#xff0c;能实…

websocket 请求头报错 Provisional headers are shown 的解决方法

今日简单总结 websocket 使用过程中遇到的问题&#xff0c;主要从以下三个方面来分享&#xff1a; 1、前端部分 websocket 代码 2、使用 koa.js 实现后端 websocket 服务搭建 3、和后端 java Netty 库对接时遇到连接失败问题 一、前端部分 websocket 代码 <template>…

Spark和Hadoop的安装

实验内容和要求 1&#xff0e;安装Hadoop和Spark 进入Linux系统&#xff0c;完成Hadoop伪分布式模式的安装。完成Hadoop的安装以后&#xff0c;再安装Spark&#xff08;Local模式&#xff09;。 2&#xff0e;HDFS常用操作 使用hadoop用户名登录进入Linux系统&#xff0c;启动…

Flink基础概念及算子

Flink基础概念-算子 一、Flink概述二、Flink集群角色和核心概念1.Flink运行时架构&#xff08;Standealone会话模式&#xff09;2.并行度&#xff08;Parallelism&#xff09;3.算子链&#xff08;Operator Chain&#xff09;4. 任务槽&#xff08;Task Slots&#xff09; 三、…

GO环境及入门案例

文章目录 简介一、win GO开发环境安装二、Linux go运行环境二、GO代码入门2.1 导包案例2.2 赋值2.3 变量、函数2.4 三方库使用 简介 go不是面向对象语言&#xff0c; 其指针、结构体等比较像C&#xff0c;知名的go 开源项目有docker k8s prometheus node-exporter等 一、win …

C语言语法进阶

条件运算符 条件运算符是 C 语言中唯一的一种三目运算符。三目运算符代表有三个操作数&#xff1b;双目 运算符代表有两个操作数&#xff0c;如逻辑与运算符就是双目运算符&#xff1b;单目运算符代表有一个操作数&#xff0c; 如逻辑非运算符就是单目运算符。运算符也称操作符…

arping命令详解

arping – send ARP REQUEST to a neighbour host. arping 是一个在网络中发送 ARP 请求以查找特定 IP 地址对应的 MAC 地址的命令行工具。它的功能类似于 ping 命令&#xff0c;基于ARP协议报文的交互机制&#xff0c;只能测试同一网段或子网的网络主机的连通性。 ARP 是 Add…

软件杯 深度学习实现行人重识别 - python opencv yolo Reid

文章目录 0 前言1 课题背景2 效果展示3 行人检测4 行人重识别5 其他工具6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的行人重识别算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c…

如何使用JSONB类型在PostgreSQL中存储和查询复杂的数据结构?

文章目录 解决方案1. 创建包含JSONB列的表2. 插入JSONB数据3. 查询JSONB数据4. 创建索引以优化查询性能 示例代码结论 在PostgreSQL中&#xff0c;JSONB是一种二进制格式的JSON数据类型&#xff0c;它允许你在数据库中存储和查询复杂的JSON数据结构。与普通的JSON类型相比&…

《操作系统导论》第27章读书笔记:插叙:线程API

《操作系统导论》第27章读书笔记&#xff1a;插叙&#xff1a;线程API —— 2024-04-21 杭州 上午 本章讲得比较啰嗦&#xff0c;问题是本章的二级标题后面都会作为一个章节来讲&#xff0c;所以本章属于概况介绍类章节&#xff0c;另外这几个并发的章节使用的都是是POSIX线程…

【python】启动一个公司级项目的完整报错和解决方案

启动一个项目对于新手都是不容易的事情 操作 打开项目 使用pyCharm打开python项目以后&#xff0c;先找main方法&#xff0c;一般在根目录有一个.py的文件 点进去以后会让你配置Python解释器 每个项目都有自己的一个虚拟环境&#xff0c;配置自己的解释器&#xff0c;可能…

windows驱动开发-设备栈

设备栈是windows内核中非常重要的部分&#xff0c;这部分理解可以让我们在调试中节省大量的时间&#xff0c; 在windows NT体系中&#xff0c;内核所有的设备被按照连接次序加载到设备树上&#xff0c;这棵树的根节点是ROOT节点&#xff0c;每一个设备可以从当前路径一直遍历到…

QMT和Ptrade有什么区别?该如何选择?

QMT&#xff08;Quantitative Model Trading&#xff09;和Ptrade&#xff08;Professional Trading&#xff09;是两种不同的交易策略和方法&#xff0c;它们在金融市场中被广泛应用。了解它们的区别有助于投资者根据自己的需求和目标做出选择&#xff1a; QMT&#xff08;量…