赞
踩
本文包含鸿蒙ArkTs加载适用于鸿蒙os专用的so库与Linux/Android通用so库两部分
如果你手上有c源代码参考笔者这篇文章编译一份适用于鸿蒙ArkTs的so动态库教学,提供给第三方导入并使用
如果你手上的so库是适用于ArkTs的(类似于Node的 C/C++ addons with N-API),直接在代码中使用
import xxx from 'libxxx.so'
如果没报错且xxx是个空对象那么恭喜你,你手上的那份so并非适用于鸿蒙os且看下文指引
一份通用Linux/Android so动态库。
如果已经有了跳到第2步
以cJson为例,拷贝代码并打开目录
linux环境下
gcc -march=armv8-a -fPIC -shared -o cjosn.so cJSON.c
得到一份armv8-a平台的cjson.so linux通用so库
可以选择native模版创建也可以创建普通工程,将native需要的文件都复制过去
把你的so库甩到libs目录对应平台下不要尝试把x86_64的so库丢进去arm目录去,回天乏力了,救救孩子吧
官方的说明,我们是导入linux通用so,所以无视他
打开/src/main/cpp/CMakeLists.txt
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(loadSo)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
#你的模块名叫hello最终会生成一个libhello.so的动态库
#从hello.c 编译出动态库
#在ArkTs中使用import xxx from 'libhello.so' 来导入你的胶水层并使用
add_library(hello SHARED hello.c)
#链接你的hello使用n-api库
target_link_libraries(hello PUBLIC libace_napi.z.so)
打开你的/src/main/cpp/hello.c(鸿蒙navtive工程模版),修改代码
#include "napi/native_api.h" #include <dlfcn.h> 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; static napi_value Add(napi_env env, napi_callback_info info) { /* 接收来之ArkTs传递过来的参数,我们没有,注释掉 size_t requireArgc = 2; size_t argc = 2; napi_value args[2] = {nullptr}; napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); napi_valuetype valuetype0; napi_typeof(env, args[0], &valuetype0); napi_valuetype valuetype1; napi_typeof(env, args[1], &valuetype1);*/ napi_value result; ///加载cjson.so void *hande = dlopen("cjson.so", RTLD_LAZY); if (!hande) { //加载失败 char *fail = "死翘翘了"; napi_create_string_utf8(env, fail, strlen(fail), &result); //将加载失败原因甩到ArkTs层,可以在try catch中获捕到 napi_throw_error(env, NULL, dlerror()); return result; } // cjson.c 的cJSON_CreateObject函数 cJSON *(*cJSON_CreateObject)(void) = (cJSON * (*)()) dlsym(hande, "cJSON_CreateObject"); //调用cJSON_CreateObject cJSON *cObject = (*cJSON_CreateObject)(); char *returnStr = "你很棒呀!加油打工人"; cObject->valuestring = returnStr; //创建一个ArkTs object 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); //把相应值丢到ArkTs object中 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", (cObject->string)? string:NULL); napi_set_named_property(env, result, "valuedouble", valuedouble); //返回这个ArkTs object return result; } static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { //这里是暴露给ArkTs可以直接调用的函数 {"cJSON_CreateObject", NULL, Add, 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 = "hello", .nm_priv = ((void *)0), .reserved = {0}, }; //入口函数 __attribute__((constructor)) void RegisterEntryModule(void) { //给ArkTs注册可以直接调用的函数列表 napi_module_register(&demoModule); }
鸿蒙官方文档: Native API在应用工程中的使用指导
鸿蒙官方文档: Node-Api
Node官方文档: C/C++ addons with N-API这份文档仅供参考,鸿蒙并没有完全实现里面所有接口,且底层实现不一致。
import hello from 'libhello.so' @Entry @Component struct Index { @State message: string = 'Hello World' aboutToAppear() { try { const cObject = hello.cJSON_CreateObject(); this.message = cObject.valuestring; } catch (e: any) { this.message = e.toString(); } } build() { Text(this.message) } }
不出意外的话,你的胶水已经粘牢了
当然!你也可能出现各种意外,毕竟你使用了来历不明的so库。
错误可以在catch里捕获
一些错误示例
你可能你的so非linux/android的库,比如适用于drwin的so
你的so库依赖别的库,需要将错误提示中的相关库一并丢/libs/arm64-v8a相关平台目录
创作不易,赠人玫瑰,手有余香,觉得有用,点个赞吧
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。