1# NDK Usage
2
3
4## Where can I find the libc++ library? Is it packed into the HAP? (API version 10)
5
6**Solution**
7
8You can find **libc++_shared.so** in the application directory. Each application has an independent **libc++_shared.so** file in **/data/storage/el1/bundle/libs/${arch}**.
9
10## How do I run a third-party open source C/C++ library on the system? (API version 10)
11
12**Solution**
13
14Currently, the official SDK supports only build with CMake. It also provides guides for GN build.
15
16**Reference**
17
181. GN build:
19
20    [Building a Third-Party Library Based on 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)
21
22    [Porting OHOS Based on a Third-Party Build Framework](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)
23
242. CMake build:
25
26    linux: [HOW TO USE NDK (linux)](https://gitee.com/openharmony/build/wikis/NDK/HOW%20TO%20USE%20NDK%20(linux))
27
28    windows: [HOW TO USE NDK (windows)](https://gitee.com/openharmony/build/wikis/NDK/HOW%20TO%20USE%20NDK%20(windows))
29
30## What are the common attributes to be used and how do I implement the APIs when using Node-API to extend TS interfaces? How do I obtain env, implement callback- and promise-based APIs, and use libuv? (API version 10)
31
32
33
34**Solution**
35
361. **env** uses the modular programming of Node-API. After the module is registered, the APIs in the callbacks are invoked with the callbacks.
37
38    ```cpp
39    static napi_value CallNapi(napi_env env, napi_callback_info info)
40    {
41        size_t argc = 1;
42        napi_value object = nullptr;
43        napi_status status;
44        status = napi_get_cb_info(env, info, &argc, &object, nullptr, nullptr);
45        return object;
46    }
47    NAPI_MODULE_INIT()
48    {
49        napi_property_descriptor desc[] = {
50            {" callNapi ", nullptr, CallNapi, nullptr, nullptr, nullptr, napi_default, nullptr}};
51        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
52        return exports;
53    }
54    ```
55
562. Callback implementation:
57
58    ```cpp
59    #include "napi/native_api.h"
60    #include <assert.h>
61    static napi_value NativeCall(napi_env env, napi_callback_info info)
62    {
63        size_t argc = 1;
64        napi_value args[1] = {nullptr};
65        napi_status status;
66        status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
67        assert(status == napi_ok);
68
69        napi_valuetype valuetype;
70        napi_typeof(env, args[0], &valuetype);
71        if (valuetype != napi_valuetype::napi_function)
72        {
73            napi_throw_type_error(env, nullptr, "napi_function is expected");
74        }
75        napi_value cb = args[0];
76
77        napi_value undefined;
78        status = napi_get_undefined(env, &undefined);
79        assert(status == napi_ok);
80
81        napi_value argv[2] = {nullptr};
82        status = napi_create_int32(env, 1, &argv[0]);
83        assert(status == napi_ok);
84        status = napi_create_int32(env, 2, &argv[1]);
85        assert(status == napi_ok);
86
87        napi_value result;
88        status = napi_call_function(env, undefined, cb, 2, argv, &result);
89        assert(status == napi_ok);
90
91        return nullptr;
92    }
93    EXTERN_C_START
94    static napi_value Init(napi_env env, napi_value exports)
95    {
96        napi_property_descriptor desc[] = {
97            {"nativeCall", nullptr, NativeCall, nullptr, nullptr, nullptr, napi_default, nullptr}};
98        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
99        return exports;
100    }
101    EXTERN_C_END
102    static napi_module module = {
103        .nm_version = 1,
104        .nm_flags = 0,
105        .nm_filename = nullptr,
106        .nm_register_func = Init,
107        .nm_modname = "callback",
108        .nm_priv = nullptr,
109        .reserved = {0},
110    };
111    extern "C" __attribute__((constructor)) void RegisterCallbackModule(void)
112    {
113        napi_module_register(&module);
114    }
115    ```
116
1173. Promise implementation:
118
119    ```cpp
120    #include "napi/native_api.h"
121
122    // Empty value so that macros here are able to return NULL or void
123    #define NAPI_RETVAL_NOTHING // Intentionally blank
124
125    #define GET_AND_THROW_LAST_ERROR(env)
126    do
127    {
128        const napi_extended_error_info *errorInfo = nullptr;
129        napi_get_last_error_info((env), &errorInfo);
130        bool isPending = false;
131        napi_is_exception_pending((env), &isPending);
132        if (!isPending && errorInfo != nullptr)
133        {
134            const char *errorMessage =
135                errorInfo->error_message != nullptr ? errorInfo->error_message : "empty error message";
136            napi_throw_error((env), nullptr, errorMessage);
137        }
138    } while (0)
139
140    #define NAPI_ASSERT_BASE(env, assertion, message, retVal)
141    do {
142        if (!(assertion))
143        {
144            napi_throw_error((env), nullptr, "assertion(" #assertion ") failed : " message);
145            return retVal;
146        }
147    } while (0)
148
149    #define NAPI_ASSERT(env, assertion, message) NAPI_ASSERT_BASE(env, assertion, message, nullptr)
150
151    #define NAPI_ASSERT_RETURN_VOID(env, assertion, message)
152        NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING)
153
154    #define NAPI_CALL_BASE(env, theCall, retVal)
155        do
156        {
157            if ((theCall) != napi_ok)
158            {
159                GET_AND_THROW_LAST_ERROR((env));
160                return retVal;
161            }
162        } while (0)
163
164    #define NAPI_CALL(env, theCall) NAPI_CALL_BASE(env, theCall, nullptr)
165
166    #define NAPI_CALL_RETURN_VOID(env, theCall) NAPI_CALL_BASE(env, theCall, NAPI_RETVAL_NOTHING)
167
168    struct AsyncData{
169        napi_deferred deferred;
170        napi_async_work work;
171
172        int32_t arg;
173        double retVal;
174    };
175
176    double DoSomething(int32_t val)
177    {
178        if (val != 0)
179        {
180            return 1.0 / val;
181        }
182        return 0;
183    }
184
185    void ExecuteCallback(napi_env env, void *data)
186    {
187        AsyncData* asyncData = reinterpret_cast<AsyncData*>(data);
188        asyncData->retVal = DoSomething(asyncData->arg);
189    }
190
191    void CompleteCallback(napi_env env, napi_status status, void *data)
192    {
193        AsyncData* asyncData = reinterpret_cast<AsyncData*>(data);
194
195        napi_value retVal;
196        if (asyncData->retVal == 0)
197        {
198            NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, "arg can't be zero", NAPI_AUTO_LENGTH, &retVal));
199            NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncData->deferred, retVal));
200        }
201        else
202        {
203            NAPI_CALL_RETURN_VOID(env, napi_create_double(env, asyncData->retVal, &retVal));
204            NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncData->deferred, retVal));
205        }
206
207        NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, asyncData->work));
208        asyncData->work = nullptr;
209        asyncData->deferred = nullptr;
210        delete asyncData;
211    }
212
213    static napi_value NativeCall(napi_env env, napi_callback_info info)
214    {
215        size_t argc = 1;
216        napi_value args[1] = {nullptr};
217        NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
218
219        int32_t arg;
220        NAPI_CALL(env, napi_get_value_int32(env, args[0], &arg));
221
222        // Create promise
223        napi_deferred deferred;
224        napi_value promise;
225        NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
226
227        AsyncData *data = new AsyncData;
228        data->deferred = deferred;
229        data->arg = arg;
230
231        napi_async_work work;
232        napi_value workName;
233        napi_create_string_utf8(env, "promise", NAPI_AUTO_LENGTH, &workName);
234        NAPI_CALL(env, napi_create_async_work(env, nullptr, workName,
235            ExecuteCallback, CompleteCallback, data, &work));
236
237        data->work = work;
238        NAPI_CALL(env, napi_queue_async_work(env, work));
239
240        return promise;
241    }
242
243    EXTERN_C_START
244    static napi_value Init(napi_env env, napi_value exports)
245    {
246        napi_property_descriptor desc[] = {
247            {"nativeCall", nullptr, NativeCall, nullptr, nullptr, nullptr, napi_default, nullptr}
248        };
249        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
250        return exports;
251    }
252    EXTERN_C_END
253
254    static napi_module demoModule = {
255        .nm_version = 1,
256        .nm_flags = 0,
257        .nm_filename = nullptr,
258        .nm_register_func = Init,
259        .nm_modname = "promise",
260        .nm_priv = nullptr,
261        .reserved = {0},
262    };
263
264    extern "C" __attribute__((constructor)) void RegisterPromiseModule(void)
265    {
266        napi_module_register(&demoModule);
267    }
268    ```
269
2704. To use libuv, import the libuv library.
271
272## How is a raw file read by the thread created by pthread? (API version 10)
273
274**Solution**
275
276The raw file can be read by a thread-safe function:
2771. Obtain and save a resource file object via the UI main thread.
2782. Create a thread-safe function.
2793. Call the thread-safe function in a non-main thread.
2804. Read the file resources in **rawfile** via the thread-safe function.
281
282## How is the processing result of a c++ thread created by an ArkTS thread using Node-API returned to the ArkTS thread? (API version 10)
283
284**Solution**
285
286Use **napi_create_threadsafe_function** to create a function that can be called by any thread in the ArkTS thread. Call **napi_call_threadsafe_function** in the C++ thread to return the result to the main thread.
287
288**References**
289
290[Thread Safety Development Using Node-API](../napi/use-napi-thread-safety.md)
291
292## What should I do to permanently hold a JS object created by napi_create_object or passed in as a parameter? (API version 10)
293
294**Question**
295
296What should I do if I need to permanently hold a JS object created by **napi_create_object** or passed in as a parameter, and destroy, increment, and decrement the reference count?
297
298**Solution**
299
300To hold an object persistently, use **napi_create_reference** to create a strong reference and then save the reference for use. To destroy a reference, use **napi_delete_reference**. To increment the reference count, use **napi_reference_ref**; to decrement the reference count, use **api_reference_unref**.
301
302## Can messages from C++ be passed to an ArkTS callback or object wrapped in a native object and synced to the application? (API version 11)
303
304**Question**
305
306Can messages from C++ be synced to an application via an ArkTS callback or object wrapped in a native object? Can **napi_env** of the ArkTS object or function be held permanently? Does a specific thread is required for syncing messages to an application?
307
308**Solution**
309
310An ArkTS object or function cannot be wrapped to a native object. You need to implement the related processing in C++. **env** can be held for a long period of time, but must be used in the ArkTS thread that creates **env**.
311
312**Reference**
313
3141. [Wrapping a Native Object in an ArkTS Object](../napi/use-napi-object-wrap.md)
315
316