如何使用napi_add_env_cleanup_hook接口注册一个环境清理钩子函数?

阅读 697
avatarAI BotBETA
要在 Node.js 原生插件中使用 `napi_add_env_cleanup_hook` 接口注册一个环境清理钩子函数,你需要按照以下步骤进行:

1. **引入必要的头文件**:
   确保你的项目中包含了 Node-API(N-API)的头文件。

#include <node_api.h>


2. **定义你的清理钩子函数**:
创建一个符合 `napi_addon_env_cleanup_hook` 类型的函数。这个函数将在 Node.js 环境被销毁时调用。

void cleanup_hook(void* arg, napi_env env) {

   // 在这里执行你的清理逻辑
   // arg 是你在注册钩子时传递的参数
   printf("Environment cleanup hook called\n");

}


3. **注册清理钩子**:
在插件初始化时(通常在 `NAPI_MODULE_INIT` 宏定义的函数中),使用 `napi_add_env_cleanup_hook` 注册你的清理钩子函数。

napi_value Init(napi_env env, napi_value exports) {

   napi_status status;
   void* hook_data = NULL; // 你可以传递任何你需要的数据给清理钩子

   // 注册环境清理钩子
   status = napi_add_env_cleanup_hook(env, cleanup_hook, hook_data, NULL);
   if (status != napi_ok) {
       // 处理错误
       napi_throw_error(env, NULL, "Failed to add environment cleanup hook");
       return NULL;
   }

   // 插件的其他初始化代码...

   return exports;

}

NAPI_MODULE_INIT() {

   return Init(env, exports);

}


这样,当你加载并使用这个插件时,一旦 Node.js 环境被销毁,`cleanup_hook` 函数就会被调用,允许你执行必要的清理操作。
1 个回答

在C++代码中,先定义资源相关的数据结构(如Memory结构体用于管理内存资源),实现外部缓冲区清理回调函数(如ExternalFinalize),在创建外部缓冲区对象时指定该回调函数,然后定义清理操作函数(如Cleanup),最后调用napi_add_env_cleanup_hook接口注册清理钩子函数,传入环境、清理操作函数和钩子函数参数(如静态变量hookArghookParameter)。示例代码如下:

#include <hilog/log.h>
#include <string>
#include "napi/native_api.h"

typedef struct {
    char *data;
    size_t size;
} Memory;

void ExternalFinalize(napi_env env, void *finalize_data, void *finalize_hint) {
    Memory *wrapper = (Memory *)finalize_hint;
    free(wrapper->data);
    free(wrapper);
    OH_LOG_INFO(LOG_APP, "Node-API napi_add_env_cleanup_hook ExternalFinalize");
}

static void Cleanup(void *arg) {
    OH_LOG_INFO(LOG_APP, "Node-API napi_add_env_cleanup_hook cleanuped: %{public}d", *(int *)(arg));
}

static napi_value NapiEnvCleanUpHook(napi_env env, napi_callback_info info) {
    std::string str("Hello from Node-API!");
    Memory *wrapper = (Memory *)malloc(sizeof(Memory));
    wrapper->data = (char *)malloc(str.size());
    strcpy(wrapper->data, str.c_str());
    wrapper->size = str.size();
    napi_value buffer = nullptr;
    napi_create_external_buffer(env, wrapper->size, (void *)wrapper->data, ExternalFinalize, wrapper, &buffer);
    static int hookArg = 42;
    static int hookParameter = 1;
    napi_status status = napi_add_env_cleanup_hook(env, Cleanup, &hookArg);
    if (status!= napi_ok) {
        napi_throw_error(env, nullptr, "Test Node-API napi_add_env_cleanup_hook failed.");
        return nullptr;
    }
    status = napi_add_env_cleanup_hook(env, Cleanup, &hookParameter);
    if (status!= napi_ok) {
        napi_throw_error(env, nullptr, "Test Node-API napi_add_env_cleanup_hook failed.");
        return nullptr;
    }
    napi_remove_env_cleanup_hook(env, Cleanup, &hookArg);
    return buffer;
}

ArkTS侧通过与Worker线程通信来调用该接口(如在主线程和Worker线程中分别发送和接收消息,在Worker线程中调用testNapi.napiEnvCleanUpHook())。
本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。