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