如何在Native层加载so库

在Native层加载so库

HarmonyOS
2024-05-28 21:46:52
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
nn_wzy

在Native层的C/C++代码环境,so库动态加载是使用dlopen()、dlsym()和dlclose()这三个函数实现的。它们的作用分别是:

  • dlopen()打开一个动态链接库,返回一个动态链接库的句柄;
  • dlsym()根据动态链接库句柄和符号名,返回动态链接库内的符号地址,这个地址既可以是变量指针,也可以是函数指针;
  • dlclose()关闭动态链接库句柄,并对动态链接库的引用计数减1,当这个库的引用计数为0,这个库将会被系统卸载。

一般使用C/C++实现so库动态加载,流程如下:

首先调用dlopen()函数,这个函数所需的参数,一个是so库的路径,一个是加载模式。一般使用的加载模式有两个:

  • RTLD_NOW在返回前解析出所有未定义符号,如果解析不出来,dlopen()返回NULL;
  • RTLD_LAZY则只解析当前需要的符号(只对函数生效,变量定义仍然是全部解析)。

显然对于动态加载,加载方只需知道当前被加载的so库里面自己需要用的函数和变量定义,所以这里选择的是后者。如果这个调用成功将返回一个so库的句柄;

在上一步得到so库句柄之后,这时就可以调用dlsym()函数,传入so库句柄和所需的函数或变量名称,返回相应的函数指针或变量指针;加载方这时就可以使用返回的指针调用被加载so库之中定义的函数和数据结构;

当so库的调用结束,调用dlclose()函数关闭卸载so库;

如果在打开关闭so库,或者获取so库里操作对象的指针出现错误的时候,可以调用dlerror()函数获取具体的错误原因。

Native侧代码实现

<CMakeLists.txt> 
 
# the minimum version of CMake. 
cmake_minimum_required(VERSION 3.4.1) 
project(OpenCl) 
include_directories(${CMAKE_SOURCE_DIR}/include) 
link_directories(${CMAKE_SOURCE_DIR}/libs) 
add_library(entry SHARED hello.cpp) 
target_link_libraries(entry libace_napi.z.so libhilog_ndk.z.so) 
<hello.cpp> 
 
#include "napi/native_api.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <dlfcn.h> 
#define LOG_TAG "name1111111111" 
#include <hilog/log.h> 
 
  //add接口,里面写对应的业务逻辑 
  static napi_value Add(napi_env env, napi_callback_info info) 
{ 
  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); 
 
  double value0; 
  napi_get_value_double(env, args[0], &value0); 
 
  double value1; 
  napi_get_value_double(env, args[1], &value1); 
 
  napi_value sum; 
  napi_create_double(env, value0 + value1, &sum); 
 
  int a, b; 
  void *p; 
  int (*func)(int, int); 
  scanf("%d%d", &a, &b); 
  // dlopen两个参数,第一个是想要打开的so库路径,第二个参数是加载模式 
  p = dlopen("/vendor/lib64/libnpu_slog.so", RTLD_NOW | RTLD_LOCAL); 
  if (p == NULL) { 
    OH_LOG_INFO(LOG_APP, "dlopenNull: dlopen error!"); 
    exit(0); 
  } else 
    OH_LOG_INFO(LOG_APP, "dlopenSuccess: dlopen ok!"); 
  dlclose(p); 
  return sum; 
} 
 
//导出add接口 
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 } 
}; 
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); 
}
分享
微博
QQ
微信
回复
2024-05-29 23:06:32
相关问题
如何在native获取屏幕亮度
670浏览 • 1回复 待解决
ArkTS和Native如何动态加载、卸载so
885浏览 • 1回复 待解决
Native如何集成三方SO
1005浏览 • 1回复 待解决
Native工程中如何使用其他三方so
994浏览 • 1回复 待解决
如何在Native侧释放ArkTS对象
1070浏览 • 1回复 待解决
如何在Native侧获取APP版本信息
973浏览 • 1回复 待解决
DevEco Studio开发如何引入.so
9137浏览 • 1回复 待解决
native如何通过命令行编译成so
1350浏览 • 1回复 待解决
ArkTS项目如何调用已有SO?
377浏览 • 1回复 待解决
native如何访问rawfile的二进制文件
887浏览 • 1回复 待解决
通过Native 调用c++实现文本绘制
481浏览 • 1回复 待解决
如何在Native侧构建一个ArkTS对象
819浏览 • 1回复 待解决
Native侧进行跨模块加载
246浏览 • 1回复 待解决
如何在DOM树加载前后运行JS脚本
614浏览 • 1回复 待解决
Native文件所在路径
901浏览 • 1回复 待解决