开发者使用napi扩展TS接口时,常用的属性和实现接口的基本用法是什么?例如怎么获取env,怎么实现callback和promise,怎么使用libuv?

北向实践与赋能 显示全部楼层 发表于 2024-1-4 10:59:03

开发者使用napi扩展TS接口时,常用的属性和实现接口的基本用法是什么?例如怎么获取env,怎么实现callback和promise,怎么使用libuv?

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

精彩评论1

北向实践与赋能

沙发 发表于 2024-1-4 10:59:36

开发者使用napi扩展TS接口时,常用的属性和实现接口的基本用法是什么?例如怎么获取env,怎么实现callback和promise,怎么使用libuv?

关键字

napi

解决方案

  1. env是使用napi的模块化编程,注册模块之后,调用回调的时候会通过回调函数调用过来:

    static napi_value CallNapi(napi_env env, napi_callback_info info)
    {
        size_t argc = 1;
        napi_value object = nullptr;
        napi_status status;
        status = napi_get_cb_info(env, info, &argc, &object, nullptr, nullptr);
        return object;
    }
     
    NAPI_MODULE_INIT() {
        napi_property_descriptor desc[] = {
            { ""callNapi"", nullptr, CallNapi, nullptr, nullptr, nullptr, napi_default, nullptr }
        };
        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
        return exports;
    }
  2. callback实现:

    #include ""napi/native_api.h""
    #include <assert.h>
     
    static napi_value NativeCall(napi_env env, napi_callback_info info)
    {
        size_t argc = 1;
        napi_value args[1] = { nullptr };
        napi_status status;
        status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
        assert(status == napi_ok);
     
        napi_valuetype valuetype;
        napi_typeof(env, args[0], &valuetype);
        if (valuetype != napi_valuetype::napi_function) {
            napi_throw_type_error(env, nullptr, ""napi_function is expected"");
        }
        napi_value cb = args[0];
     
        napi_value undefined;
        status = napi_get_undefined(env, &undefined);
        assert(status == napi_ok);
     
        napi_value argv[2] = { nullptr };
        status = napi_create_int32(env, 1, &argv[0]);
        assert(status == napi_ok);
        status = napi_create_int32(env, 2, &argv[1]);
        assert(status == napi_ok);
        
        napi_value result;
        status = napi_call_function(env, undefined, cb, 2, argv, &result);
        assert(status == napi_ok);
        
        return nullptr;
    }
     
    EXTERN_C_START
    static napi_value Init(napi_env env, napi_value exports)
    {
        napi_property_descriptor desc[] = {
            { ""nativeCall"", nullptr, NativeCall, 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 module = {
        .nm_version = 1,
        .nm_flags = 0,
        .nm_filename = nullptr,
        .nm_register_func = Init,
        .nm_modname = ""callback"",
        .nm_priv = nullptr,
        .reserved = { 0 },
    };
     
    extern ""C"" __attribute__((constructor)) void RegisterCallbackModule(void)
    {
        napi_module_register(&module);
    }
  3. promise实现参考:

    #include ""napi/native_api.h""
     
    // Empty value so that macros here are able to return NULL or void
    #define NAPI_RETVAL_NOTHING  // Intentionally blank
     
    #define GET_AND_THROW_LAST_ERROR(env)                                                                   \
        do {                                                                                                \
            const napi_extended_error_info* errorInfo = nullptr;                                            \
            napi_get_last_error_info((env), &errorInfo);                                                    \
            bool isPending = false;                                                                         \
            napi_is_exception_pending((env), &isPending);                                                   \
            if (!isPending && errorInfo != nullptr) {                                                       \
                const char* errorMessage =                                                                  \
                    errorInfo->error_message != nullptr ? errorInfo->error_message : ""empty error message""; \
                napi_throw_error((env), nullptr, errorMessage);                                             \
            }                                                                                               \
        } while (0)
     
    #define NAPI_ASSERT_BASE(env, assertion, message, retVal)                                    \
        do {                                                                                     \
            if (!(assertion)) {                                                                  \
                napi_throw_error((env), nullptr, ""assertion ("" #assertion "") failed: "" message); \
                return retVal;                                                                   \
            }                                                                                    \
        } while (0)
     
    #define NAPI_ASSERT(env, assertion, message) NAPI_ASSERT_BASE(env, assertion, message, nullptr)
     
    #define NAPI_ASSERT_RETURN_VOID(env, assertion, message) \
            NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING)
     
    #define NAPI_CALL_BASE(env, theCall, retVal) \
        do {                                     \
            if ((theCall) != napi_ok) {          \
                GET_AND_THROW_LAST_ERROR((env)); \
                return retVal;                   \
            }                                    \
        } while (0)
     
    #define NAPI_CALL(env, theCall) NAPI_CALL_BASE(env, theCall, nullptr)
     
    #define NAPI_CALL_RETURN_VOID(env, theCall) NAPI_CALL_BASE(env, theCall, NAPI_RETVAL_NOTHING)
     
    struct AsyncData {
        napi_deferred deferred;
        napi_async_work work;
        
        int32_t arg;
        double retVal;
    };
     
    double DoSomething(int32_t val)
    {
        if (val != 0) {
            return 1.0 / val; 
        }
        return 0;
    }
     
    void ExecuteCallback(napi_env env, void* data)
    {
        AsyncData* asyncData = reinterpret_cast<AsyncData*>(data);
        asyncData->retVal = DoSomething(asyncData->arg);
    }
     
    void CompleteCallback(napi_env env, napi_status status, void* data)
    {
        AsyncData* asyncData = reinterpret_cast<AsyncData*>(data);
     
        napi_value retVal;
        if (asyncData->retVal == 0) {
    NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, ""arg can't be zero"", NAPI_AUTO_LENGTH, &retVal));
            NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncData->deferred, retVal));
        } else {
            NAPI_CALL_RETURN_VOID(env, napi_create_double(env, asyncData->retVal, &retVal));
            NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncData->deferred, retVal));
        }
     
        NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, asyncData->work));
        asyncData->work = nullptr;
        asyncData->deferred = nullptr;
        delete asyncData;
        
    }
     
    static napi_value NativeCall(napi_env env, napi_callback_info info)
    {
        size_t argc = 1;
        napi_value args[1] = { nullptr };
        NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
     
        int32_t arg;
        NAPI_CALL(env, napi_get_value_int32(env, args[0], &arg));
     
        // Create promise
        napi_deferred deferred;
        napi_value promise;
        NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
     
        AsyncData* data = new AsyncData;
        data->deferred = deferred;
        data->arg = arg;
     
        napi_async_work work;
        napi_value workName;
    napi_create_string_utf8(env, ""promise"", NAPI_AUTO_LENGTH, &workName);
        NAPI_CALL(env, napi_create_async_work(env, nullptr, workName,
            ExecuteCallback, CompleteCallback, data, &work));
        
        data->work = work;
        NAPI_CALL(env, napi_queue_async_work(env, work));
     
        return promise;
    }
     
    EXTERN_C_START
    static napi_value Init(napi_env env, napi_value exports)
    {
        napi_property_descriptor desc[] = {
            { ""nativeCall"", nullptr, NativeCall, 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 = ""promise"",
        .nm_priv = nullptr,
        .reserved = { 0 },
    };
     
    extern ""C"" __attribute__((constructor)) void RegisterPromiseModule(void)
    {
        napi_module_register(&demoModule);
    }
  4. libuv使用:可以直接导入libuv三方库使用

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部