转载注明出处
这里以cJSON为例,只需要使用到仓库的cJSON.h和cJSON.c
打开DevEco-Studio创建一个native项目
选项随意填写
将cJSON.c和cJSON.h放到项目自动创建的cpp文件夹下
在cmakelists.txt添加两行
add_library(cjson SHARED cJSON.c)
target_link_libraries(cjson PUBLIC libace_napi.z.so)
cjson表示最终导出的so库的名字(libcjson.so)
cJOSN.c表示使用这个文件编译出动态so链接库
在build->outputs->default可找到打包出来的hap
我们解压这个hap
得到3个平台的so动态链接库
也可以直接在build->intermediates->libs->default里找到对应平台的so库不需要解压hap
可在项目的build-profile配置abiFilters,不写默认导出3个平台的so
现在我们就得到了一份看起来不太聪明的so动态链接库
创建一个普通项目
将刚刚生成的3个平台的so库放到libs对应平台的文件夹里,目录没有可手动创建,平台的so不能混用,放对位置。
在Arkts中使用so库并调用函数
import cjson from 'libcjson.so'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
aboutToAppear() {
let a= cjson;
console.log(JSON.stringify(cjson));
cjson.cJSON_CreateObject();
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
不出意外,得到一个undefined
ArkTs加载的so库类似node的napi,不能直接调用c的函数需要我们自己封装一层,用于连接ArkTs和c function 可参考官方文档
按照指引我们返回创建的native项目对cJSON.c进行修改,添加一些函数
打开cJSON.c
在文件末尾添加头文件和注册函数
void Fn_cJSON_CreateObject() {
}
#include "napi/native_api.h"
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
{"cJSON_CreateObject", NULL, Fn_cJSON_CreateObject, NULL, NULL, NULL, napi_default, NULL}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = NULL,
.nm_register_func = Init,
.nm_modname = "cjson",
.nm_priv = ((void *)0),
.reserved = {0},
};
__attribute__((constructor)) void RegisterEntryModule(void) {
napi_module_register(&demoModule);
}
desc[]数组每一项都是暴露给ArkTs可以直接调用的函数
你需要在ArkTs中使用到的所有c函数都需要添加进去,用不到的不需要添加
我们暂时暴露cJSON_CreateObject这个函数作为例子
Fn_cJSON_CreateObject名字随意取,cJSON_CreateObject名字是暴露给ArkTs使用的,也是随意取,现在我们修改Fn_cJSON_CreateObject,用于调用c的cJSON_CreateObject函数
napi_value Fn_cJSON_CreateObject(napi_env env, napi_callback_info info) {
cJSON *cObject = cJSON_CreateObject();
/*size_t requireArgc = 2;
size_t argc = 2;
napi_value args[2] = {NULL};
napi_get_cb_info(env, info, &argc, args, NULL, NULL);
napi_valuetype valuetype0;
napi_typeof(env, args[0], &valuetype0);
napi_valuetype valuetype1;
napi_typeof(env, args[1], &valuetype1);*/
char *returnStr = "你很棒呀!加油打工人";
napi_value result;
napi_create_string_utf8(env, returnStr, strlen(returnStr), &result);
return result;
}
第一行调用c的cJSON_CreateObject函数
注释部分是用于接收来至ArkTs的参数,我们没传,所以暂时注释掉
这里暂时返回一个 字符串 加油打工人!
重复 第3步和第4步
编译出so库,在新项目中导入替换旧so的并使用
在新项目中修改代码并运行,得到我们想要的预期结果
import cjson from 'libcjson.so'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
aboutToAppear() {
let a = cjson;
const result = cjson.cJSON_CreateObject();
console.log(result)
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
好了,现在我们已经成功连接ArkTs和c function了,到这已经结束了
cJSON_CreateObject函数返回的是一个cJson的结构体,我们只返回了一个字符串,对应到ArkTs因该为一个Object对象,接着我们继续修改代码,返回c函数结构体真正对应到ArkTs的Object
查看cJSON.h
cJSON的结构体
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
转换成ArkTs的数据结构便是
interface cJSON {
next: cJSON
prev: cJSON
child: cJSON
type: number
valuestring: string
valueint: number
valuedouble: number
string: string
}
修改Fn_cJSON_CreateObject
napi_value Fn_cJSON_CreateObject(napi_env env, napi_callback_info info) {
cJSON *cObject = cJSON_CreateObject();
/*size_t requireArgc = 2;
size_t argc = 2;
napi_value args[2] = {NULL};
napi_get_cb_info(env, info, &argc, args, NULL, NULL);
napi_valuetype valuetype0;
napi_typeof(env, args[0], &valuetype0);
napi_valuetype valuetype1;
napi_typeof(env, args[1], &valuetype1);*/
napi_value result;
char *returnStr = "你很棒呀!加油打工人";
cObject->valuestring = returnStr;
napi_create_object(env, &result);
napi_value type;
napi_create_int32(env, cObject->type, &type);
napi_value valueint;
napi_create_int32(env, cObject->valueint, &valueint);
napi_value valuestring;
napi_create_string_utf8(env, cObject->valuestring ? cObject->valuestring : "", strlen(cObject->valuestring), &valuestring);
napi_value string;
if (cObject->string) {
napi_create_string_utf8(env, cObject->string, strlen(cObject->string), &string);
}
napi_value valuedouble;
napi_create_double(env, cObject->valuedouble, &valuedouble);
napi_value next, prev, child;
napi_create_reference(env, NULL, 1, &next);
napi_create_reference(env, NULL, 1, &prev);
napi_create_reference(env, NULL, 1, &child);
napi_set_named_property(env, result, "type", type);
napi_set_named_property(env, result, "valueint", valueint);
napi_set_named_property(env, result, "valuestring", valuestring);
napi_set_named_property(env, result, "string", string ? string : NULL);
napi_set_named_property(env, result, "valuedouble", valuedouble);
napi_set_named_property(env, result, "next", next);
napi_set_named_property(env, result, "prev", prev);
napi_set_named_property(env, result, "child", child);
return result;
}
觉得有用的不忘点个赞,转载注明出处,有任何疑问欢迎在评论区提出。