ArkTS侧与Native侧分别如何动态加载SO库 ?

ArkTS侧与Native侧分别如何动态加载SO库

阅读 6.4k
avatarAI BotBETA

在ArkTS侧(假设你指的是TypeScript或JavaScript环境,因为"ArkTS"不是一个标准术语),动态加载SO库(Shared Object库,通常是C或C++编译的动态链接库)通常是通过Node.js的ffiffi-napi库来实现的。这些库允许你在JavaScript或TypeScript中调用本地C函数。

以下是一个使用ffi-napi库动态加载SO库的简单示例:

const ffi = require('ffi-napi');
const ref = require('ref-napi');

// 定义SO库中的函数签名
const myFunction = ffi.Function('void', ['int']);

// 加载SO库
const lib = ffi.Library('path/to/your/library.so', {
  'myFunction': myFunction,
});

// 调用SO库中的函数
lib.myFunction(123);

在Native侧(假设是C或C++环境),动态加载SO库通常使用dlopendlsymdlclose等函数。以下是一个简单的C++示例:

#include <dlfcn.h>
#include <iostream>

int main() {
    // 打开SO库
    void* handle = dlopen("path/to/your/library.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "dlopen failed: " << dlerror() << std::endl;
        return 1;
    }

    // 获取函数指针
    typedef void (*MyFunctionType)(int);
    MyFunctionType myFunction = (MyFunctionType)dlsym(handle, "myFunction");
    const char* dlsymError = dlerror();
    if (dlsymError) {
        std::cerr << "dlsym failed: " << dlsymError << std::endl;
        dlclose(handle);
        return 1;
    }

    // 调用函数
    myFunction(123);

    // 关闭SO库
    dlclose(handle);

    return 0;
}

请注意,动态加载SO库涉及到平台相关性和错误处理,因此在实际应用中需要更加谨慎和详细的错误处理。此外,确保SO库的路径是正确的,并且你的程序有权限访问它。

1 个回答

1.ArkTS可通过动态import的方式动态加载so库。

2.Native侧可通过dlopen动态加载so库。

参考代码如下:

1.ArkTS可通过动态import的方式动态加载so库。添加异步函数,在异步函数中通过let testNapi = await import("libentry.so")实现动态加载so库。

import { hilog } from '@kit.PerformanceAnalysisKit'; 
// import testNapi from 'libentry.so'; 
 
@Entry 
@Component 
struct Index { 
  @State message: string = 'Hello World'; 
 
  build() { 
    Row() { 
      Column() { 
        Text(this.message) 
          .fontSize(50) 
          .fontWeight(FontWeight.Bold) 
          .onClick(async() => { 
            let testNapi = await import("libentry.so")            // 加载so库 
            hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.default.add(2, 3));   // 通过default调用库函数 
            // hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

2.Native侧可通过dlopen动态加载so库。

假设这里我们需要调用liba.so中的add函数。

首先需要将liba.so文件放到libs/arm64-v8a/路径下。

image.png

然后需要我们在ArkTS侧传递so库路径信息到Native侧。

import { hilog } from '@kit.PerformanceAnalysisKit'; 
import testNapi from 'libentry.so'; 
 
@Entry 
@Component 
struct Index { 
  @State message: string = 'Hello World'; 
 
  build() { 
    Row() { 
      Column() { 
        Text(this.message) 
          .fontSize(50) 
          .fontWeight(FontWeight.Bold) 
          .onClick(() => { 
            let path = getContext(this).bundleCodeDir;     // 获取项目路径 
            hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3, path + '/libs/arm64/liba.so'));   // 传递参数路径信息到Native侧 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

然后在Native侧通过dlopen函数动态加载so库

#include "napi/native_api.h" 
#include <dlfcn.h> 
typedef double (*FUNC_ADD)(int, int); 
static napi_value Add(napi_env env, napi_callback_info info) { 
    size_t requireArgc = 3; 
    size_t argc = 3; 
    napi_value args[3] = {nullptr}; 
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 
    double value0; 
    napi_get_value_double(env, args[0], &value0); 
    double value1; 
    napi_get_value_double(env, args[1], &value1); 
    char path[255]; 
    size_t size = 255; 
    napi_get_value_string_utf8(env, args[2], path, 255, &size); // 获取动态库路径信息 
    void *handle = dlopen(path, RTLD_LAZY);                     // 打开一个动态链接库.路径为path 
    dlerror(); 
    FUNC_ADD add_func = (FUNC_ADD)dlsym(handle, "add"); // 获取函数名为add的函数 
    if (dlerror()) { 
        return nullptr; 
    } 
    double res = add_func(value0, value1);              // 调用add并传递参数信息 
    dlclose(handle);                                    // 最后记得close动态库 
    napi_value sum; 
    napi_create_double(env, res, &sum); 
    return sum; 
} 
// ...
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进