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

news2024/9/19 10:38:48

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。希望可以帮助到大家!!!

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

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

相关文章

使用FPGA实现比较器

介绍 比较器就是通过比较输入的大小&#xff0c;然后输出给出判断。 在这个比较器中&#xff0c;有两个输入&#xff0c;三个输出。根据输出就可以判断出哪个输入值大了。 设计文件 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity compa…

JAVA----Thread

Thread 这里写目录标题 Thread线程Thread 第 1 种写法此外, t.start()的作用 Thread 第 2 种写法Thread 第 3 种写法Thread 第 4 种写法Thread 第 5 种写法 线程 本身是操作系统提供的, 操作系统提供了 API 以让我们操作线程, JVM 就对操作系统 API 进行了封装. 线程这里, 则提…

verilog变量类型wire、reg和Memory的介绍和用法

目录 wire型 reg型 Memory型 wire型 wire 类型变量&#xff0c;也叫网络类型变量&#xff0c;用于结构实体之间的物理连接&#xff0c;如门与门之间&#xff0c;不能储存值&#xff0c;用连续赋值语句 assign 赋值&#xff0c;定义为 wire [n-1:0] a ; 其中 n 代表位宽&…

OCT2Former: A retinal OCT-angiography vessel segmentationtransformer论文总结

论文(COMPUT METH PROG BIO)&#xff1a;OCT2Former: A retinal OCT-angiography vessel segmentation transformer 源码&#xff1a;https://github.com/coreeey/OCT2Former 一、摘要 背景与目的&#xff1a;视网膜血管分割在视网膜疾病自动筛查与诊断中起着重要作用。如何分…

面试高频:HTTPS 通信流程

更多大厂面试内容可见 -> http://11come.cn 面试高频&#xff1a;HTTPS 通信流程 HTTPS 的加密流程 接下来说一下 HTTPS 协议是如何进行通信的&#xff1a; HTTPS 通信使用的 对称加密 非对称加密 两者结合的算法 HTTPS 通信时&#xff0c;会先使用 非对称加密 让通信双…

大sql mysql执行

先把sql 拆分 太大的执行失败 使用 SQLDumpSplitter3 拆分sql 执行拆分的sql 拆分的sql 打开发现很多 ; 开头的空行 替换掉 正则 ^; 修改数据库 my.cnf my,ini 执行可能会提示 [ERR] 2006 - Server has gone away 错误 在 [mysqld] 添加以下几行 wait_timeout2880000 inter…

Qt基础之四十六:Qt界面中嵌入第三方程序的一点心得

本文主要讲解QWidget和QWindow的区别,以及如何在QWidget中嵌入第三方程序,并完美解决在QWidget中嵌入某些程序(比如Qt程序)时出现的白边问题。 下面是嵌入QQ音乐的样子,这首歌还不错。 先用spy++查看QQ音乐的窗口信息,如果安装了Visual Studio,工具菜单里自带spy++ 然后…

【1471】java项目进度管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 项目进度管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

【Linux】自定义协议——实现网络序列化和反序列化

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;承接上文内容【Linux】应用层协议序列化和反序列化 目录 &#x1f449;&#x1f3fb;代码实现如下Calculate.hp…

企业常用Linux三剑客awk及案例/awk底层剖析/淘宝网cdn缓存对象分级存储策略案例/磁盘知识/awk统计与计算-7055字

高薪思维&#xff1a; 不愿意做的事情:加班&#xff0c;先例自己在利他 生活中先利他人在利自己 感恩&#xff0c;假设别人帮助过你&#xff0c;先帮助别人&#xff0c;感恩境界 awk三剑客老大 find其实也算是一种新的第四剑客 find 查找文件 查找文件&#xff0c;与其他命令…

【UnityShader】图片圆角

1.需求 我们在开发的时候&#xff0c;有时候一些按钮或者菜单栏的边角是直角的需要改成圆角&#xff0c;但是让美术重新绘制耽误时间不说也确实没必要&#xff0c;这个时候我们不妨使用一个简单的shader去解决这个问题&#xff0c;下面我们就讲讲这个shader要如何实现。 需求1…

设计模式之观察者模式(优先使用对象组合的原则)的C++实现

观察者模式又称订阅者发布者模式&#xff0c;本篇介绍主要是利用对象组合大于类继承的设计模式原则实现订阅发布模式&#xff0c;这种设计的优点是想订阅数据的类不需要继承订阅者类的抽象类&#xff0c;减少了一层类的继承&#xff1b;当然&#xff0c;具体情况需要可根据需求…

在ios设备上运行Unity Profiler

久违了朋友们。 最近基于Unity 2021.3 和AR Foundation开发了个应用&#xff0c;需要在ipad上实际运行时查看程序的各项指标功耗。 于是乎&#xff0c;我尝试跟随者官方教程来实时调试&#xff0c;现在附上一些心得。 按照官方的三步走&#xff0c;Build and Run理论上会自动…

42岁TVB男艺人曾靠刘德华贴钱出道,苦熬10年终上位

张颕康在无线&#xff08;TVB&#xff09;电视打滚多年&#xff0c;近年在《逆天奇案》第一、二辑凭扎实演技为人留下印象。他还是圈中出名的「爱妻号」&#xff0c;日前在访问期间&#xff0c;张颕康三句不离多谢太太。 较年长的观众或会记得&#xff0c;张颕康初出道以「刘德…

边缘计算智能分析网关V4地面垃圾AI检测算法介绍及场景应用

在传统的卫生监管场景中&#xff0c;无法及时发现地面遗留的垃圾&#xff0c;通过人工巡逻的方式需要大量的人力、物力和时间&#xff0c;而且效率不高&#xff0c;并存在一定的滞后性&#xff0c;而采用地面垃圾AI检测算法则可以大大提高监管效率。 TSINGSEE青犀AI智能分析网…

骑砍2霸主MOD开发(6)-使用C#-Harmony修改本体游戏逻辑

一.C#-Harmony反射及动态注入 利用C#运行时环境的反射原理,实现对已加载DLL,未加载DLL中代码替换和前置后置插桩. C#依赖库下载地址:霸王•吕布 / CSharpHarmonyLib GitCodehttps://gitcode.net/qq_35829452/csharpharmonylib 根据实际运行.Net环境选择对应版本的0Harmony.dll…

【编译原理】03语法分析

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

MyBatis 核心配置讲解(上)

大家好&#xff0c;我是王有志&#xff0c;一个分享硬核 Java 技术的互金摸鱼侠。 前两篇的文章中我们分别介绍了 MyBatis 和 MyBaits 的应用组成&#xff0c;到这里基础篇的内容就结束了。 从今天开始&#xff0c;我们正式进入 MyBatis 学习的第二阶段&#xff1a;MyBatis 的…

插值与重采样在AI去衣技术中的关键作用

在人工智能&#xff08;AI&#xff09;的众多应用中&#xff0c;去衣技术作为一种新兴的图像处理技术&#xff0c;逐渐引起了广泛关注。这项技术不仅涉及复杂的计算机视觉和深度学习算法&#xff0c;还需要对图像处理中的插值与重采样技术有深入的理解。本文将详细探讨插值与重…

【笔试训练】day7

1.在字符串中找出连续最长的数字串 思路&#xff1a; 简单双指针&#xff0c;随便怎么暴力 代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include<string> using namespace std;int main() {string str;cin >> str;int ans …