【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_lib
    hilog_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_END

static 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.编码json
    cJSON *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_SetValuestring
    cJSON_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);
        
    //释放 jsonObj
    cJSON_Delete(jsonObj);
    return modifyJson;
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

决策树分类任务实战(python 代码详解)

目录 一、导入库、数据集、并划分训练集和测试集 二、参数调优 (一)第一种调参方法&#xff1a;for循环 (1)单参数优化 ①单参数优化(无K折交叉验证) ②单参数K折交叉验证 优化 (2)多参数优化 ①多参数优化(无K折交叉验证) 参数介绍&#xff1a; ②多参数K折交叉验证…

ruoyi-vue前端的一些自定义插件介绍

文章目录 自定义列表$tab对象打开页签关闭页签刷新页签 $modal对象提供成功、警告和错误等反馈信息&#xff08;无需点击确认&#xff09;提供成功、警告和错误等提示信息&#xff08;类似于alert&#xff0c;需要点确认&#xff09;提供成功、警告和错误等提示信息&#xff08…

常见现代卷积神经网络(ResNet, DenseNet)(Pytorch 11)

一 批量规范化&#xff08;batch normalization&#xff09; 训练深层神经网络是十分困难的&#xff0c;特别是在较短的时间内使他们收敛更加棘手。批量规范化&#xff08;batch normalization&#xff09;是一种流行且有效的技术&#xff0c;可持续加速深层网络的收敛速度。 …

数据结构与算法解题-20240421

数据结构与算法解题-20240421 一、278. 第一个错误的版本二、541. 反转字符串 II三、右旋字符串四、替换数字五、977.有序数组的平方 一、278. 第一个错误的版本 简单 你是产品经理&#xff0c;目前正在带领一个团队开发新的产品。不幸的是&#xff0c;你的产品的最新版本没有…

数据可视化(七):Pandas香港酒店数据高级分析,涉及相关系数,协方差,数据离散化,透视表等精美可视化展示

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

centos7搭建git服务器

1.centos7安装git yum install -y git yum install -y git-daemon 2.初始化空目录仓库 mkdir /usr/local/git mkdir /usr/local/git/projects mkdir /usr/local/git/projects/test-projects.git cd test-projects.git git --bare init 3.修改目录权限 cd .. chmod 775 tes…

力扣283. 移动零

Problem: 283. 移动零 文章目录 题目描述思路复杂度Code 题目描述 思路 1.定义一个int类型变量index初始化为0&#xff1b; 2.遍历nums当当前的元素nums[i]不为0时使nums[i]赋值给nums[index]&#xff1b; 3.从index开始将nums中置对应位置的元素设为0&#xff1b; 复杂度 时间…

第三届 SWCTF-Web 部分 WP

写在前面 题目主要涉及的是前端 php 内容知识&#xff0c;仅以本篇博客记录自己 Web 出题的奇思妙想。 Copyright © [2024] [Myon⁶]. All rights reserved. 目录 1、HTTP 2、再见了晚星 3、myon123_easy_php 4、baby_P0P 5、LOGIN!!! 1、HTTP 首页文件默认就是 ind…

基于Hadoop的电商用户行为分析系统设计与实现的系统架构设计

采集层&#xff1a;利用Flume采集电商服务器端用户行为数据&#xff0c;把数据处理后发送至HDFS。 存储层&#xff1a;用户行为数据采集上传至HDFS存储&#xff0c; 导入到数据仓库Hive进行计算处理&#xff0c;分析结果保存至MySql数据库中。 计算层&#xff1a;根据分析需求建…

Dynamic Wallpaper for Mac激活版:视频动态壁纸软件

Dynamic Wallpaper for Mac 是一款为Mac电脑量身打造的视频动态壁纸应用&#xff0c;为您的桌面带来无限生机和创意。这款应用提供了丰富多样的视频壁纸选择&#xff0c;涵盖了自然风景、抽象艺术、科幻奇观等多种主题&#xff0c;让您的桌面成为一幅活生生的艺术画作。 Dynami…

将记录从excel当中导出为.sql文件,再新增到数据库

一、背景 临时遇到了一个需求&#xff0c;比如根据人员的名字查询对应记录&#xff0c;看起来还是很简单的&#xff0c;直接用select查询就可以&#xff0c;然而如果此时存在以下情况&#xff1a; 数据库根本就没有人员信息表&#xff1b;------这个倒是好操作&#xff1b;现…

R: 阿尔法α多样性计算和箱图制作,以及差异分析

# install.packages("vegan") library(vegan) library(ggplot2) library(ggpubr)setwd("xxx") # 使用read.table()函数读取数据 df <- read.table("xxx", header TRUE, row.names 1)# 转置数据框 df <- t(df)# 计算每个样品的香农多样性…

【声呐仿真】学习记录1.5-使用docker配置dave(先看这个!)、解决一些问题

【声呐仿真】学习记录1.5-使用docker配置dave、解决一些问题 docker配置dave123 以下为未完全解决问题的随手记录&#xff0c;待日后解决再补充1.pcap、png解决&#xff0c;libusb未解决&#xff08;不要修改libusb相关的&#xff09;2.ISO C3.换源4.自动安装相关依赖 docker配…

Excel数据处理:动态数据分析报表、单元格数字格式、使用排序工具

1、在生成数据透视表之后选中一个单元格&#xff0c;点击插入&#xff0c;在图表中选择一个自己想要的图表。&#xff08;生成可视化的图表&#xff09; 2、在分析中找到切片器&#xff0c;通过点击切片器可以即时变换生成不同的可视化图&#xff0c;可以右键切片器选择关联两个…

怎么用 today函数求月份的汇总?

怎样用today函数来求以下表格中11月、12月的总额呢&#xff1f; 在excel里&#xff0c;可识别的日期实际上也是数值&#xff0c;这样的条件汇总&#xff0c;妨用SUMPRODUCT函数。 一、使用SUMPRODUCT函数 SUMPRODUCT((TEXT(A2:A5,"e-m")TEXT(EDATE(TODAY(),-1),&qu…

Llama3新一代 Llama模型

最近&#xff0c;Meta 发布了 Llama3 模型&#xff0c;从发布的数据来看&#xff0c;性能已经超越了 Gemini 1.5 和 Claud 3。 Llama 官网说&#xff0c;他们未来是要支持多语言和多模态的&#xff0c;希望那天赶紧到来。 未来 Llama3还将推出一个 400B大模型&#xff0c;目前…

【大模型应用极简开发入门(2)】GPT模型简史:从GPT-1到GPT-4:从小数据量的微调到大数据量的强化学习不断优化模型

文章目录 一. GPT-1&#xff1a;无监督与微调1. 在GPT-1之前的监督学习的问题2. GPT-1中新的学习过程-无监督的预训练3. 复杂任务下的微调4. GPT-1为更强大的模型铺平了道路 二. GPT-2&#xff1a;context learning1. 核心思想&#xff1a;context learning2. GPT-2的数据集 三…

【编译原理】03语法分析

1&#xff0c;语法分析的若干问题 1.1 语法分析器的作用 编译器前端的重要组成部分&#xff1a; (1) 根据词法分析器提供的记号流&#xff0c;为语法正确的输入构造分析树(或语法树)。 (2) 检查输入中的语法(可能包括词法)错误&#xff0c;并调用出错处理器进…

如何在一台服务器上同时运行搭载JDK 8, JDK 17, 和 JDK 21的项目:终极指南

&#x1f42f; 如何在一台服务器上同时运行搭载JDK 8, JDK 17, 和 JDK 21的项目&#xff1a;终极指南 &#x1f680; 摘要 在企业开发环境中&#xff0c;常常需要在同一台服务器上运行使用不同Java开发工具包&#xff08;JDK&#xff09;版本的多个项目。本文详细介绍如何在L…

Linux——进程基本概念中篇

Linux——进程基本概念中篇 文章目录 Linux——进程基本概念中篇一、通过系统调用创建进程——fork1.1 fork的理解1.2 fork的返回值 二、进程状态2.1 运行状态2.2 睡眠状态和休眠状态2.3 停止状态和死亡状态2.4 僵尸进程2.5 孤儿进程2.6 前台和后台进程 三、进程优先级3.1 查看…