harmony 鸿蒙Setting ArkTS Object Properties Using Node-API
Setting ArkTS Object Properties Using Node-API
Introduction
Node-API provides APIs for obtaining and setting properties of ArkTS objects in C/C++. Properly using these APIs help to implement more complex functionalities and logic.
Basic Concepts
Before working with ArkTS objects using Node-API, you need to understand the following concepts:
- Object: a composite data type that allows values of different types in an independent entity in ArkTS. An object is a collection of properties and methods. A property is a value associated with the object, and a method is an operation that the object can perform.
- Property: a feature, in the key-value format, of an object in ArkTS. Each property has a name (key or identifier) and a value. The property value can be of any data type, including the basic type, object, and function.
- Enumerable property: a property in ArkTS with enumerable set to true. An enumerable property can be traversed by for…in.
- Own property: a property defined for an object rather than inherited from the prototype chain.
Available APIs
The following table lists the APIs for manipulating ArkTS object properties.
|API|Description|
|——–|——–|
|napi_get_property_names|Obtains the names of the enumerable properties of an object in an array of strings.|
|napi_set_property|Adds a property to an object or modifies a property value of an object.|
|napi_get_property|Obtains the requested property of an object. You can use this API to obtain the property value of an ArkTS object and pass it to another function for processing.|
|napi_has_property|Checks whether an object has the specified property. Before a property is accessed, you can call this API to check whether the object has this property. This can prevent the exception or error caused due to the absence of the property.|
|napi_delete_property|Deletes a property from an ArkTS object.|
|napi_has_own_property|Checks whether an object has the specified own property.|
|napi_set_named_property|Sets a property with the specified name for an ArkTS object.|
|napi_get_named_property|Obtains the value of a property in an ArkTS object.|
|napi_has_named_property|Checks whether an ArkTS object has the property with the specified name.|
|napi_define_properties|Defines multiple properties for an ArkTS object.|
|napi_get_all_property_names|Obtains the names of all properties of an ArkTS object.|
Example
If you are just starting out with Node-API, see Node-API Development Process. The following demonstrates only the C++ and ArkTS code related to property management.
napi_get_property_names
Call napi_get_property_names to obtain the names of the enumerable properties of an object in an array of strings.
CPP code:
#include "napi/native_api.h"
static napi_value GetPropertyNames(napi_env env, napi_callback_info info)
{
// Parse the ArkTS input parameters.
size_t argc = 1;
napi_value args[1] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// Obtain the names of all the enumerable properties of the object in the form of a string array and output the string array in result.
napi_value result;
napi_status status = napi_get_property_names(env, args[0], &result);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "Node-API napi_get_property_names fail");
return nullptr;
}
return result;
}
API declaration:
// index.d.ts
export const getPropertyNames: (obj: Object) => Array<string>|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
try {
class Obj {
data: number = 0
message: string = ""
}
let obj: Obj = { data: 0, message: "hello world"};
let propertyNames = testNapi.getPropertyNames(obj);
if (Array.isArray(propertyNames) && propertyNames.length > 0) {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_property_names: %{public}s', propertyNames[0]);
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_property_names: %{public}s', propertyNames[1]);
}
} catch (error) {
hilog.error(0x0000, 'testTag', 'Test Node-API napi_get_property_names error: %{public}s', error.message);
}
napi_set_property
Call napi_set_property to set a property for an object.
CPP code:
#include "napi/native_api.h"
static constexpr int INT_ARG_2 = 2; // Input parameter index.
static napi_value SetProperty(napi_env env, napi_callback_info info)
{
// Obtain the parameters passed from ArkTS. The first parameter specifies the object, the second parameter specifies the property name, and the third parameter specifies the property value to set.
size_t argc = 3;
napi_value args[3] = {nullptr};
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "Node-API napi_get_cb_info fail");
}
// Call napi_set_property to set the property name and value to the object. If the operation fails, throw an error.
status = napi_set_property(env, args[0], args[1], args[INT_ARG_2]);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "Node-API napi_set_property fail");
return nullptr;
}
// Return the object that is successfully set.
return args[0];
}
API declaration:
// index.d.ts
export const setProperty: (obj: Object, key: String, value: string) => Object|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
try {
class Obj {
data: number = 0
message: string = ""
}
let obj: Obj = { data: 0, message: "hello world"};
let result = testNapi.setProperty(obj, "code", "hi");
hilog.info(0x0000, 'testTag', 'Test Node-API napi_set_property: %{public}s', JSON.stringify(result));
} catch (error) {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_set_property error: %{public}s', error.message);
}
napi_get_property
Call napi_get_property to obtain the value of the specified property in an object.
CPP code:
#include "napi/native_api.h"
static napi_value GetProperty(napi_env env, napi_callback_info info)
{
// Obtain the two parameters passed from ArkTS.
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// The first parameter specifies the target object, and the second specifies the property name. Call napi_get_property to obtain the value of the property.
napi_value result;
napi_status status = napi_get_property(env, args[0], args[1], &result);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "Node-API napi_get_property fail");
return nullptr;
}
return result;
}
API declaration:
// index.d.ts
export const getProperty: (obj: Object, key: string) => string|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
try {
class Obj {
data: number = 0
message: string = ""
}
let obj: Obj = { data: 0, message: "hello world"};
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_property: %{public}s', testNapi.getProperty(obj, "message"));
} catch (error) {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_property error: %{public}s', error.message);
}
napi_has_property
Call napi_has_property to check whether an object has the specified property. This can prevent the exception or error caused by access to a property that does not exist.
CPP code:
#include "napi/native_api.h"
static napi_value HasProperty(napi_env env, napi_callback_info info)
{
// Pass in two parameters from ArkTS. The first parameter specifies the target object, and the second parameter specifies the property to check.
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// Pass the parameters to napi_has_property. If the API is successfully called, convert the result to napi_value and return napi_value. Otherwise, throw an error.
bool result;
napi_status status = napi_has_property(env, args[0], args[1], &result);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "Node-API napi_has_property fail");
return nullptr;
}
// If the property exists in the object, output true, convert the result to napi_value, and return napi_value.
napi_value returnResult;
napi_get_boolean(env, result, &returnResult);
return returnResult;
}
API declaration:
// index.d.ts
export const hasProperty: (obj: Object, key: number|string) => boolean|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
try {
class Obj {
data: number = 0
message: string = ""
}
let obj: Obj = { data: 0, message: "hello world"};
let resultFalse = testNapi.hasProperty(obj, 0);
let resultTrue = testNapi.hasProperty(obj, "data");
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_property: %{public}s', JSON.stringify(resultFalse));
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_property: %{public}s', JSON.stringify(resultTrue));
} catch (error) {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_property error: %{public}s', error.message);
}
napi_delete_property
Call napi_delete_property to delete the property specified by key from an object. If the object is a non-extensible object or the property is not configurable, the property cannot be deleted.
CPP code:
#include "napi/native_api.h"
// Delete the specified property from the object and return a bool value indicating whether the deletion is successful.
static napi_value DeleteProperty(napi_env env, napi_callback_info info)
{
// Obtain the two parameters passed from ArkTS.
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
napi_valuetype valueType;
napi_typeof(env, args[0], &valueType);
if (valueType != napi_object) {
napi_throw_error(env, nullptr, "Expects an object as argument.");
return nullptr;
}
// Delete the specified property and store the operation result in result.
bool result = false;
napi_status status = napi_delete_property(env, args[0], args[1], &result);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "Node-API napi_delete_property failed");
return nullptr;
}
// Convert the bool value to napi_value and return it.
napi_value ret;
napi_get_boolean(env, result, &ret);
return ret;
}
API declaration:
// index.d.ts
export const deleteProperty: (obj: Object, key:string) => boolean;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
class Obj {
first: number = 0;
}
let obj: Obj = { first: 1};
hilog.info(0x0000, 'testTag', 'Test Node-API napi_delete_property first: %{public}s', testNapi.deleteProperty(obj, 'first'));
// Set the new property to unconfigurable.
// The Object.defineProperty method is not supported in DevEco Studio 4.1.0.400 or later. It must be used in TS.
Object.defineProperty(obj, 'config', {
configurable: false,
value: "value"
})
hilog.info(0x0000, 'testTag', 'Test Node-API napi_delete_property config: %{public}s', testNapi.deleteProperty(obj, 'config'));
napi_has_own_property
Call napi_has_own_property to check whether an ArkTS object has its own property.
CPP code:
#include "napi/native_api.h"
static napi_value NapiHasOwnProperty(napi_env env, napi_callback_info info)
{
// Obtain the two parameters passed from ArkTS.
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// Check whether the first parameter is an object.
napi_valuetype valueTypeObj;
napi_typeof(env, args[0], &valueTypeObj);
if (valueTypeObj != napi_object) {
napi_throw_error(env, nullptr, "First argument must be an object.");
return nullptr;
}
// Check whether the second parameter is a string.
napi_valuetype valuetypeStr;
napi_typeof(env, args[1], &valuetypeStr);
if (valuetypeStr != napi_string) {
napi_throw_error(env, nullptr, "Second argument must be a string.");
return nullptr;
}
// Check whether the object has the specified property and returns the result in hasProperty.
bool hasProperty;
napi_status status = napi_has_own_property(env, args[0], args[1], &hasProperty);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "napi_has_own_property failed");
return nullptr;
}
// Convert the bool value to napi_value and return it.
napi_value result;
napi_get_boolean(env, hasProperty, &result);
return result;
}
API declaration:
// index.d.ts
export const napiHasOwnProperty: (obj: Object, key:string) => boolean|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
let myObj = { 'myProperty': 1 };
let inheritedObj = { 'inheritedProperty': 2 };
// The Object.setPrototypeOf method is not supported in DevEco Studio 4.1.0.400 or later. It must be used in TS.
Object.setPrototypeOf(myObj, inheritedObj);
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_own_property my: %{public}s', testNapi.napiHasOwnProperty(myObj, 'myProperty'));
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_own_property inherited: %{public}s', testNapi.napiHasOwnProperty(myObj, 'inheritedProperty'));
napi_set_named_property
Call napi_set_named_property to set a property for an ArkTS object.
CPP code:
#include "napi/native_api.h"
static napi_value NapiSetNamedProperty(napi_env env, napi_callback_info info)
{
// Obtain the parameter passed from ArkTS.
size_t argc = 1;
napi_value str;
const int32_t strLength = 32;
char strKey[strLength] = "";
napi_get_cb_info(env, info, &argc, &str, nullptr, nullptr);
// Obtain the string passed in and store it in strKey.
size_t keyLength;
napi_get_value_string_utf8(env, str, strKey, strLength, &keyLength);
// Create an object.
napi_value newObj;
napi_create_object(env, &newObj);
// Set the property value to 1234.
int32_t value = 1234;
napi_value numValue;
napi_create_int32(env, value, &numValue);
// Associate the integer value with the property name.
napi_status status = napi_set_named_property(env, newObj, strKey, numValue);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "napi_set_named_property failed");
return nullptr;
}
// Return the newObj object with the specified property set.
return newObj;
}
API declaration:
// index.d.ts
export const napiSetNamedProperty: (key: string) => Object|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
let obj = testNapi.napiSetNamedProperty('myProperty');
let objAsString = JSON.stringify(obj);
hilog.info(0x0000, 'testTag', 'Test Node-API napi_set_named_property: %{public}s', objAsString);
napi_get_named_property
Call napi_get_named_property to obtain the value of the specified property from an ArkTS object.
CPP code:
#include "napi/native_api.h"
static napi_value NapiGetNamedProperty(napi_env env, napi_callback_info info)
{
// Obtain the two parameters passed from ArkTS.
size_t argc = 2;
napi_value args[2] = {nullptr};
const int32_t strLength = 32;
char strKey[strLength] = "";
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// Obtain the name of the property to obtain.
size_t keyLength;
napi_get_value_string_utf8(env, args[1], strKey, strLength, &keyLength);
// Obtain the value of the property and store it in result.
napi_value result;
napi_status status = napi_get_named_property(env, args[0], strKey, &result);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "napi_get_named_property failed");
return nullptr;
}
// Return result.
return result;
}
API declaration:
// index.d.ts
export const napiGetNamedProperty: (obj: Object, key:string) => boolean|number|string|Object|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
interface NestedObj {
nestedStr: string;
nestedNum: number;
}
class Obj {
str: string = "";
num: number = 0;
bol: boolean = false;
nestedObj: NestedObj = { nestedStr: "", nestedNum: 0 };
}
let obj: Obj = {str: "bar", num: 42, bol: true,
nestedObj: { nestedStr: "nestedValue", nestedNum: 123 }};
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_named_property : %{public}s', testNapi.napiGetNamedProperty(obj, 'str'));
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_named_property : %{public}d', testNapi.napiGetNamedProperty(obj, 'num'));
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_named_property : %{public}s', testNapi.napiGetNamedProperty(obj, 'bol'));
let nestedObj = testNapi.napiGetNamedProperty(obj, 'nestedObj');
let objAsString = JSON.stringify(nestedObj);
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_named_property : %{public}s', objAsString);
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_named_property : %{public}s', testNapi.napiGetNamedProperty(obj, 'null'));
napi_has_named_property
Call napi_has_named_property to check whether an ArkTS object contains the specified property.
CPP code:
#include "napi/native_api.h"
static napi_value NapiHasNamedProperty(napi_env env, napi_callback_info info)
{
// Obtain the two parameters passed from ArkTS.
size_t argc = 2;
napi_value args[2] = {nullptr};
const int32_t strLength = 32;
char strKey[strLength] = "";
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// Obtain the property name.
size_t keyLength;
napi_get_value_string_utf8(env, args[1], strKey, strLength, &keyLength);
// Check whether the object has the specified property and stores the result in hasProperty.
bool hasProperty = false;
napi_status status = napi_has_named_property(env, args[0], strKey, &hasProperty);
if (status != napi_ok) {
napi_throw_error(env, nullptr, "napi_has_named_property failed");
return nullptr;
}
// Convert the bool value to napi_value and return it.
napi_value result;
napi_get_boolean(env, hasProperty, &result);
return result;
}
API declaration:
// index.d.ts
export const napiHasNamedProperty: (obj: Object, key:string) => boolean|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
interface NestedObj {
nestedStr: string;
nestedNum: number;
}
class Obj {
str: string = "";
num: number = 0;
bol: boolean = false;
nestedObj: NestedObj = { nestedStr: "", nestedNum: 0 };
}
let obj: Obj = {str: "bar", num: 42, bol: true,
nestedObj: { nestedStr: "nestedValue", nestedNum: 123 }};
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_named_property : %{public}s', testNapi.napiHasNamedProperty(obj, 'str'));
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_named_property : %{public}s', testNapi.napiHasNamedProperty(obj, 'nestedStr'));
hilog.info(0x0000, 'testTag', 'Test Node-API napi_has_named_property : %{public}s', testNapi.napiHasNamedProperty(obj, 'bol'));
napi_define_properties
Call napi_define_properties to define multiple properties for an ArkTS object.
CPP code:
#include <string>
#include "napi/native_api.h"
static napi_value DefineMethodPropertiesExample(napi_env env, napi_callback_info info)
{
// Create a property value of the int32 type.
int32_t propValue = 26;
napi_value returnValue = nullptr;
napi_create_int32(env, propValue, &returnValue);
return returnValue;
}
// Define a getter callback.
static napi_value GetterCallback(napi_env env, napi_callback_info info)
{
napi_value result;
const char *str = u8"World!";
size_t length = strlen(str);
// Create property values.
napi_create_string_utf8(env, str, length, &result);
return result;
}
// Define a setter callback.
static napi_value SetterCallback(napi_env env, napi_callback_info info)
{
// Obtain the parameters passed to setter.
size_t argc = 1;
napi_value argv[1] = {nullptr};
napi_value result;
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
size_t length = 0;
napi_get_value_string_utf8(env, argv[0], nullptr, 0, &length);
char* buf = new char[length + 1];
std::memset(buf, 0, length + 1);
napi_get_value_string_utf8(env, argv[0], buf, length + 1, &length);
napi_create_string_utf8(env, buf, length, &result);
delete buf;
return result;
}
static napi_value DefineMethodProperties(napi_env env, napi_callback_info info)
{
napi_value obj;
napi_create_object(env, &obj);
// Define the defineMethodPropertiesExample function for the obj object, define a variable in the defineMethodPropertiesExample function, and return the variable. When the obj object is called, the defineMethodPropertiesExample will be called.
napi_property_descriptor descriptor[] = {
{"defineMethodPropertiesExample", nullptr, DefineMethodPropertiesExample, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_define_properties(env, obj, sizeof(descriptor) / sizeof(descriptor[0]), descriptor);
return obj;
}
static napi_value DefineStringProperties(napi_env env, napi_callback_info info)
{
napi_value obj;
napi_create_object(env, &obj);
// Create a property value of the string type.
napi_value string_value;
napi_create_string_utf8(env, "Hello!", NAPI_AUTO_LENGTH, &string_value);
napi_property_descriptor descriptor[] = {
{"defineStringPropertiesExample", nullptr, nullptr, nullptr, nullptr, string_value, napi_default, nullptr}};
napi_define_properties(env, obj, sizeof(descriptor) / sizeof(descriptor[0]), descriptor);
return obj;
}
static napi_value CreateStringWithGetterSetter(napi_env env, napi_callback_info info)
{
napi_value obj;
napi_create_object(env, &obj);
// Define the getter function.
napi_value getterFn;
napi_create_function(env, nullptr, 0, GetterCallback, nullptr, &getterFn);
napi_set_named_property(env, obj, "getterCallback", getterFn);
// Define the setter function.
napi_value setterFn;
napi_create_function(env, nullptr, 0, SetterCallback, nullptr, &setterFn);
napi_set_named_property(env, obj, "setterCallback", setterFn);
// Define properties with getter and setter.
napi_property_descriptor desc = {"defineGetterSetter", nullptr, GetterCallback, SetterCallback, nullptr, obj, napi_enumerable, nullptr};
napi_define_properties(env, obj, 1, &desc);
return obj;
}
API declaration:
// index.d.ts
export class DefineMethodObj {
defineMethodPropertiesExample: Function;
}
export class DefineStringObj {
defineStringPropertiesExample: string;
}
export class DefineGetterSetterObj {
getterCallback: Function;
setterCallback: Function;
}
export const defineMethodProperties: () => DefineMethodObj;
export const defineStringProperties: () => DefineStringObj;
export const createStringWithGetterSetter: () => DefineGetterSetterObj;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
// Define a property of the method type.
hilog.info(0x0000, 'testTag', 'Test Node-API define_method_properties:%{public}d', testNapi.defineMethodProperties()
.defineMethodPropertiesExample());
// Define a property of the string type.
hilog.info(0x0000, 'testTag', 'Test Node-API define_string_properties::%{public}s ', testNapi.defineStringProperties()
.defineStringPropertiesExample);
// getter and setter.
hilog.info(0x0000, 'testTag', 'Test Node-API get::%{public}s ', testNapi.createStringWithGetterSetter()
.getterCallback());
hilog.info(0x0000, 'testTag', 'Test Node-API setter::%{public}s ', testNapi.createStringWithGetterSetter()
.setterCallback('set data'));
napi_get_all_property_names
Call napi_get_all_property_names to obtain all property names in an ArkTS object.
CPP code:
#include "napi/native_api.h"
static napi_value GetAllPropertyNames(napi_env env, napi_callback_info info)
{
// obtain the parameter.
size_t argc = 1;
napi_value args[1] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// Obtain all property names of the given object.
napi_value result;
napi_status status = napi_get_all_property_names(env, args[0], napi_key_own_only, napi_key_writable,
napi_key_numbers_to_strings, &result);
// If the operation fails, throw an error.
if (status != napi_ok) {
napi_throw_error(env, nullptr, "Node-API napi_get_all_property_names fail");
return nullptr;
}
return result;
}
API declaration:
// index.d.ts
export const getAllPropertyNames : (obj: Object) => Array<string>|void;
ArkTS code:
import hilog from '@ohos.hilog';
import testNapi from 'libentry.so';
try {
class Obj {
data: number = 0
message: string = ""
}
let obj: Obj = { data: 0, message: "hello world"};
let propertyNames = testNapi.getAllPropertyNames(obj);
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_all_property_names: %{public}s', JSON.stringify(propertyNames));
} catch (error) {
hilog.info(0x0000, 'testTag', 'Test Node-API napi_get_all_property_names error: %{public}s', error.message);
}
To print logs in the native CPP, add the following information to the CMakeLists.txt file and add the header file by using #include “hilog/log.h”.
// CMakeLists.txt
add_definitions( "-DLOG_DOMAIN=0xd0d0" )
add_definitions( "-DLOG_TAG=\"testTag\"" )
target_link_libraries(entry PUBLIC libhilog_ndk.z.so)
你可能感兴趣的鸿蒙文章
harmony 鸿蒙Building an NDK Project with CMake
harmony 鸿蒙Building an NDK Project with the DevEco Studio Template
harmony 鸿蒙NDK Project Building Overview
harmony 鸿蒙Building an NDK Project with Prebuilt Libraries
harmony 鸿蒙C/C++ Library Mechanisms
harmony 鸿蒙Creating an NDK Project
- 所属分类: 后端技术
- 本文标签:
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦