• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# NDK开发常见问题
2
3## 以libstd为例,C++的标准库放在哪里了,有没有打到hap包中?(API 10)
4
5**解决方案**
6
7libc++_shared.so被打包到应用目录下了,每个应用都有一份独立的libc++_shared.so (/data/storage/el1/bundle/libs/${arch})
8
9## C/C++的三方开源库如何迁移到系统下运行?(API 10)
10
11**解决方案**
12
13当前官方SDK只支持Cmake构建,同时对于依赖GN构建的场景提供了迁移指导
14
15**参考资料**
16
171. GN构建:
18
19    [基于gn_example编译三方库代码](https://gitee.com/openharmony/build/wikis/gn%E6%9E%84%E5%BB%BA%E4%B8%89%E6%96%B9%E5%BA%93/%E5%9F%BA%E4%BA%8Egn_example%E7%BC%96%E8%AF%91%E4%B8%89%E6%96%B9%E5%BA%93%E4%BB%A3%E7%A0%81)
20
21    [基于三方编译框架移植OHOS](https://gitee.com/openharmony/build/wikis/gn%E6%9E%84%E5%BB%BA%E4%B8%89%E6%96%B9%E5%BA%93/%E5%9F%BA%E4%BA%8E%E4%B8%89%E6%96%B9%E7%BC%96%E8%AF%91%E6%A1%86%E6%9E%B6%E7%A7%BB%E6%A4%8DOHOS)
22
232. CMake构建:
24
25    linux:[HOW TO USE NDK (linux)](https://gitee.com/openharmony/build/wikis/NDK/HOW%20TO%20USE%20NDK%20(linux))
26
27    windows:[HOW TO USE NDK (windows)](https://gitee.com/openharmony/build/wikis/NDK/HOW%20TO%20USE%20NDK%20(windows))
28
29## 开发者使用napi扩展TS接口时,常用的属性和实现接口的基本用法是什么?例如怎么获取env,怎么实现callback和promise,怎么使用libuv?(API 10)
30
31
32
33**解决方案**
34
351. env是使用napi的模块化编程,注册模块之后,调用回调的时候会通过回调函数调用过来:
36
37    ```cpp
38    static napi_value CallNapi(napi_env env, napi_callback_info info)
39    {
40        size_t argc = 1;
41        napi_value object = nullptr;
42        napi_status status;
43        status = napi_get_cb_info(env, info, &argc, &object, nullptr, nullptr);
44        return object;
45    }
46    NAPI_MODULE_INIT()
47    {
48        napi_property_descriptor desc[] = {
49            {"callNapi", nullptr, CallNapi, nullptr, nullptr, nullptr, napi_default, nullptr}};
50        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
51        return exports;
52    }
53    ```
54
552. callback实现:
56
57    ```cpp
58    #include "napi/native_api.h"
59    #include <assert.h>
60    static napi_value NativeCall(napi_env env, napi_callback_info info)
61    {
62        size_t argc = 1;
63        napi_value args[1] = {nullptr};
64        napi_status status;
65        status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
66        assert(status == napi_ok);
67
68        napi_valuetype valuetype;
69        napi_typeof(env, args[0], &valuetype);
70        if (valuetype != napi_valuetype::napi_function)
71        {
72            napi_throw_type_error(env, nullptr, "napi_function is expected");
73        }
74        napi_value cb = args[0];
75
76        napi_value undefined;
77        status = napi_get_undefined(env, &undefined);
78        assert(status == napi_ok);
79
80        napi_value argv[2] = {nullptr};
81        status = napi_create_int32(env, 1, &argv[0]);
82        assert(status == napi_ok);
83        status = napi_create_int32(env, 2, &argv[1]);
84        assert(status == napi_ok);
85
86        napi_value result;
87        status = napi_call_function(env, undefined, cb, 2, argv, &result);
88        assert(status == napi_ok);
89
90        return nullptr;
91    }
92    EXTERN_C_START
93    static napi_value Init(napi_env env, napi_value exports)
94    {
95        napi_property_descriptor desc[] = {
96            {"nativeCall", nullptr, NativeCall, nullptr, nullptr, nullptr, napi_default, nullptr}};
97        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
98        return exports;
99    }
100    EXTERN_C_END
101    static napi_module module = {
102        .nm_version = 1,
103        .nm_flags = 0,
104        .nm_filename = nullptr,
105        .nm_register_func = Init,
106        .nm_modname = "callback",
107        .nm_priv = nullptr,
108        .reserved = {0},
109    };
110    extern "C" __attribute__((constructor)) void RegisterCallbackModule(void)
111    {
112        napi_module_register(&module);
113    }
114    ```
115
1163. promise实现参考:
117
118    ```cpp
119    #include "napi/native_api.h"
120
121    // Empty value so that macros here are able to return NULL or void
122    #define NAPI_RETVAL_NOTHING // Intentionally blank
123
124    #define GET_AND_THROW_LAST_ERROR(env)
125    do
126    {
127        const napi_extended_error_info *errorInfo = nullptr;
128        napi_get_last_error_info((env), &errorInfo);
129        bool isPending = false;
130        napi_is_exception_pending((env), &isPending);
131        if (!isPending && errorInfo != nullptr)
132        {
133            const char *errorMessage =
134                errorInfo->error_message != nullptr ? errorInfo->error_message : "empty error message";
135            napi_throw_error((env), nullptr, errorMessage);
136        }
137    } while (0)
138
139    #define NAPI_ASSERT_BASE(env, assertion, message, retVal)
140    do {
141        if (!(assertion))
142        {
143            napi_throw_error((env), nullptr, "assertion(" #assertion ") failed : " message);
144            return retVal;
145        }
146    } while (0)
147
148    #define NAPI_ASSERT(env, assertion, message) NAPI_ASSERT_BASE(env, assertion, message, nullptr)
149
150    #define NAPI_ASSERT_RETURN_VOID(env, assertion, message)
151        NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING)
152
153    #define NAPI_CALL_BASE(env, theCall, retVal)
154        do
155        {
156            if ((theCall) != napi_ok)
157            {
158                GET_AND_THROW_LAST_ERROR((env));
159                return retVal;
160            }
161        } while (0)
162
163    #define NAPI_CALL(env, theCall) NAPI_CALL_BASE(env, theCall, nullptr)
164
165    #define NAPI_CALL_RETURN_VOID(env, theCall) NAPI_CALL_BASE(env, theCall, NAPI_RETVAL_NOTHING)
166
167    struct AsyncData{
168        napi_deferred deferred;
169        napi_async_work work;
170
171        int32_t arg;
172        double retVal;
173    };
174
175    double DoSomething(int32_t val)
176    {
177        if (val != 0)
178        {
179            return 1.0 / val;
180        }
181        return 0;
182    }
183
184    void ExecuteCallback(napi_env env, void *data)
185    {
186        AsyncData* asyncData = reinterpret_cast<AsyncData*>(data);
187        asyncData->retVal = DoSomething(asyncData->arg);
188    }
189
190    void CompleteCallback(napi_env env, napi_status status, void *data)
191    {
192        AsyncData* asyncData = reinterpret_cast<AsyncData*>(data);
193
194        napi_value retVal;
195        if (asyncData->retVal == 0)
196        {
197            NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "arg can't be zero", NAPI_AUTO_LENGTH, &retVal));
198            NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncData->deferred, retVal));
199        }
200        else
201        {
202            NAPI_CALL_RETURN_VOID(env, napi_create_double(env, asyncData->retVal, &retVal));
203            NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncData->deferred, retVal));
204        }
205
206        NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, asyncData->work));
207        asyncData->work = nullptr;
208        asyncData->deferred = nullptr;
209        delete asyncData;
210    }
211
212    static napi_value NativeCall(napi_env env, napi_callback_info info)
213    {
214        size_t argc = 1;
215        napi_value args[1] = {nullptr};
216        NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
217
218        int32_t arg;
219        NAPI_CALL(env, napi_get_value_int32(env, args[0], &arg));
220
221        // Create promise
222        napi_deferred deferred;
223        napi_value promise;
224        NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
225
226        AsyncData *data = new AsyncData;
227        data->deferred = deferred;
228        data->arg = arg;
229
230        napi_async_work work;
231        napi_value workName;
232        napi_create_string_utf8(env, "promise", NAPI_AUTO_LENGTH, &workName);
233        NAPI_CALL(env, napi_create_async_work(env, nullptr, workName,
234            ExecuteCallback, CompleteCallback, data, &work));
235
236        data->work = work;
237        NAPI_CALL(env, napi_queue_async_work(env, work));
238
239        return promise;
240    }
241
242    EXTERN_C_START
243    static napi_value Init(napi_env env, napi_value exports)
244    {
245        napi_property_descriptor desc[] = {
246            {"nativeCall", nullptr, NativeCall, nullptr, nullptr, nullptr, napi_default, nullptr}
247        };
248        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
249        return exports;
250    }
251    EXTERN_C_END
252
253    static napi_module demoModule = {
254        .nm_version = 1,
255        .nm_flags = 0,
256        .nm_filename = nullptr,
257        .nm_register_func = Init,
258        .nm_modname = "promise",
259        .nm_priv = nullptr,
260        .reserved = {0},
261    };
262
263    extern "C" __attribute__((constructor)) void RegisterPromiseModule(void)
264    {
265        napi_module_register(&demoModule);
266    }
267    ```
268
2694. libuv使用:可以直接导入libuv三方库使用
270
271## pthread创建的线程中如何读取rawfile?(API 10)
272
273**解决方案**
274
275可在线程安全函数中读取:
2761. UI 主线程中获取并保存资源文件对象;
2772. 创建线程安全函数;
2783. 在非UI主线程中调用线程安全函数;
2794. 在线程安全函数中,读取rawfile下的文件资源。
280
281## ArkTS线程通过napi创建的C++线程的处理结果如何返回ArkTS线程?(API 10)
282
283**解决方案**
284
285采用napi_create_threadsafe_function在ArkTS线程创建可被任意线程调用的函数,在C++线程调用napi_call_threadsafe_function可以将结果回调给主线程。
286
287**参考链接**
288
289[使用Node-API接口进行线程安全开发](../napi/use-napi-thread-safety.md)
290
291## 由napi_create_object创建,或者作为参数传下来的JS对象,如果想持久持有,需要怎么做?(API 10)
292
293**问题描述**
294
295以及,怎么主动销毁或减少引用计数?
296
297**解决方案**
298
299持久持有一个对象,可以通过napi_create_reference创建一个强引用,然后将这个ref保存下来使用;主动销毁可以使用napi_delete_reference,减少或者增加引用计数可以通过napi_reference_unref或者napi_reference_ref。
300
301## 在ArkTS层往C++层注册一个对象或函数,C++层可以按需往这个回调上进行扔消息同步到上层应用么?(API 11)
302
303**问题描述**
304
305以及,在注册对象或函数时,napi_env是否可以被长时持有?扔消息同步到上层应用时,是否需要在特定线程?
306
307**解决方案**
308
309纯在ArkTS侧不可以往C++层注册对象或者函数,开发者需要回到C++层自己处理;env可以长期持有,不过使用env时,需要在特定的线程,使用env时需要在创建该env的ArkTS线程使用。
310
311**参考资料**
312
3131. [Native与ArkTS对象绑定](../napi/use-napi-object-wrap.md)
314