openharmony 鸿蒙 use-napi-about-critical

2026-08-25 浏览 (1)

Creating and Destroying a Critical Scope and Accessing String Content Using Node-API Extension APIs

The Node-API extension APIs napi_open_critical_scope and napi_close_critical_scope are used to open and close a critical scope, respectively.

NOTE

Non-critical APIs cannot be used in a critical scope, and only one critical scope can be opened in an execution environment. You are advised to open a critical scope only when critical APIs are required, and close the scope in a timely manner after the APIs are used.

When to Use

Before calling critical APIs, you must open a critical scope using napi_open_critical_scope and call the APIs in the critical scope.

After the critical scope is closed, do not use the critical API or its return result. Otherwise, the program may crash or data may be damaged.

Opening and Closing a Critical Scope and Using Critical APIs

APIDescriptionStatus Code for Executions Outside the Critical Scope
napi_open_critical_scopeOpens a critical scope.NA
napi_close_critical_scopeCloses a critical scope.napi_generic_failure
napi_get_buffer_string_utf16_in_critical_scopeObtains the UTF-16 encoding memory buffer data of an ArkTS string.napi_generic_failure

NOTE

  1. To obtain the memory buffer of an ArkTS string stored in UTF-16-encoding format, use napi_get_buffer_string_utf16_in_critical_scope. Otherwise, an error will be returned.

  2. napi_create_string_utf16 and napi_create_string_utf8 are used to pass the input data to the VM in the specified encoding format. These functions do not control the internal storage encoding format of strings in the VM.

Sample Code

  • Register the modules.

    // napi_init.cpp
    #include <string>
    #include <string_view>
    #include <vector>
    
    #include "napi/native_api.h"
    
       // Use the C++ RAII mechanism to manage the critical scope, ensuring that the critical scope is closed.
       // This is only an example. You can also use other encapsulation methods or the original API.
       class MyCriticalScope
    {
       napi_env env_{};
       napi_critical_scope scope_{};
    
    public:
       explicit MyCriticalScope(napi_env env) : env_(env)
       {
          if (napi_open_critical_scope(env, &scope_) != napi_ok)
          {
                // If the operation fails, perform necessary error handling or maintenance information supplementation. Details are omitted here.
                // Common failure cause: env is not a valid Node-API execution context (for example, env is nullptr).
          }
       }
       ~MyCriticalScope()
       {
          Close();
       }
       inline void Close()
       {
          if (scope_ == nullptr)
          {
                return;
          }
          // Close the critical scope in the destructor.
          if (napi_close_critical_scope(env_, scope_) != napi_ok)
          {
                // If the operation fails, perform necessary error handling or maintenance information supplementation. Details are omitted here.
                // Common causes:
                // 1. The critical scope is closed repeatedly.
                // 2. env is not a valid Node-API execution context (for example, env is a null pointer).
                // 3. scope is not a valid critical scope handle (for example, scope is a null pointer).
          }
          scope_ = nullptr;
       }
    };
    
    // Secondary encapsulation method, which is used to copy the underlying buffer of an ArkTS string if failing to obtain the buffer.
    static std::vector<char16_t> GetValueStringUtf16(napi_env env, napi_value value)
    {
       size_t strLength{};
       if (napi_get_value_string_utf16(env, value, nullptr, 0, &strLength) != napi_ok) {
          return {};
       }
       /* The Node-API requires that the buffer length be greater than the string length, which is used to write the end flag of the C string.
          Therefore, to obtain the complete string, the buffer size must be the string length plus 1.*/
       std::vector<char16_t> result(strLength + 1);
       if (napi_get_value_string_utf16(env, value, result.data(), result.size(), &strLength) != napi_ok) {
          return {};
       }
       return result;
    }
    
    static napi_value NAPI_Global_getBufferStringUtf16(napi_env env, napi_callback_info info)
    {
       napi_value args[1]{};
       size_t argc = 1;
       napi_get_cb_info(env, info, &argc, args, /* thisVar */ nullptr, /* data */ nullptr);
       // The number of passed-in parameters is less than the minimum number of required parameters.
       if (argc < 1) {
          return nullptr;
       }
       napi_valuetype argType;
    
       // The parameter is not a string.
       if (napi_typeof(env, args[0], &argType) != napi_ok||argType != napi_string) {
          return nullptr;
       }
    
       uint32_t returnCode = 0;
       {
          [[maybe_unused]] MyCriticalScope scope(env);
          size_t bufSize{};
          const char16_t *buf{};
          std::vector<char16_t> copied{}; // Reserved for fallback when the buffer fails to be obtained
          std::u16string_view str;
    
          if (napi_get_buffer_string_utf16_in_critical_scope(env, args[0], &buf, &bufSize) == napi_ok)
          {
                str = std::u16string_view(buf, bufSize);
          } else {
                scope.Close();
                copied = GetValueStringUtf16(env, args[0]);
                str = std::u16string_view(copied.data(), copied.size());
                returnCode|= (1 << 1);
          }
    
          // do something with str
          if (str == u"测试字符串") {
                returnCode|= 1;
          }
       }
    
       napi_value returnResult{};
       napi_create_int32(env, returnCode, &returnResult);
       return returnResult;
    }
    
    // Register the module.
    EXTERN_C_START
    static napi_value Init(napi_env env, napi_value exports)
    {
       std::vector<napi_property_descriptor> desc{{"getBufferStringUtf16", nullptr, NAPI_Global_getBufferStringUtf16,
                                                    nullptr, nullptr, nullptr, napi_default, nullptr}};
       napi_define_properties(env, exports, desc.size(), desc.data());
       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);
    }
    
  • API declaration

    // index.d.ts
    export const getBufferStringUtf16: (str: string) => number;
    
  • ArkTS sample code

    // index.ets
    import testNapi from "libentry.so"
    
    const makeTest = (str: string) => {
       console.info(`status code of get buffer on "${str}": ${testNapi.getBufferStringUtf16(str)}`);
    }
    
    makeTest("hello world"); // Expected result: 2 or 0
    makeTest("你好");        // Expected result: 0 or 2
    makeTest("测试字符串");   // Expected result: 1 or 3
    

你可能感兴趣的鸿蒙文章

openharmony 鸿蒙 use-napi-ark-runtime

openharmony 鸿蒙 use-napi-about-arraybuffer

openharmony 鸿蒙 use-jsvm-about-array

openharmony 鸿蒙 use-napi-load-module

openharmony 鸿蒙 jsvm-data-types-interfaces

openharmony 鸿蒙 ohos-abi

openharmony 鸿蒙 jsvm-guidelines

openharmony 鸿蒙 use-jsvm-trigger-gc

openharmony 鸿蒙 use-sendable-napi

openharmony 鸿蒙 use-napi-object-wrap

  • 所属分类: 后端技术
  • 本文标签: 软件 鸿蒙
  • 版权声明: 本文链接 https://seaxiang.com/blog/FYbssCE2