4【鸿蒙/OpenHarmony/NDK】如何在鸿蒙Navite C++样例代码中新增一个js接口?
·
各位码友们好!今天这篇干货主要聚焦实操细节,希望能帮大家少踩坑。
要是过程中遇到哪块没看懂、有疑问,或者你有更优的实现思路,评论区尽管聊!发现文档里有疏漏或错误也尽管指出来 ——
技术这东西就得互相挑刺才能越磨越精,咱们一起把这些知识点吃透~
前置学习
- 在【鸿蒙/OpenHarmony/NDK】如何在鸿蒙应用中使用NDK?文章中,我们初步学习了怎么使用NDK,详细解析了NDK的Hello World 应用。
- 这篇文章我们学以致用,实际增加一个js接口,然后在C++侧实现这个接口。
声明js接口
- Native C++样例中,实现了两个数字相加。这篇文章我们来实现两个字符串的相加
ConcatenateString: (a: string, b: string) => string;,将字符串a和b拼接成一个字符串。 - 同时我们还会严格检查参数类型,个数等是否和接口定义一致,不一致时会抛出异常。
- 通过之前文章的介绍我们了解到,我们要实现的js接口都是放在
src/main/cpp/types/libentry/Index.d.ts文件中的。所以我们也将我们拼接字符串的js接口也放到该文件中,如下:
export const add: (a: number, b: number) => number;
export const ConcatenateString: (a: string, b: string) => string;
实现js接口
- Dev Eco做了非常贴心的功能,当我们添加了接口声明,但是没有接口的Native实现的时候,他会提醒你。此时我们点击
Generate native implementation它就会自动在napi_init.cpp文件中添加该接口的实现模板。

- Dev Eco自动帮我们添加了js接口
ConcatenateString和c++侧实现NAPI_Global_ConcatenateString的关联。我们只需要添加NAPI_Global_ConcatenateString的实现即可。

NAPI_Global_ConcatenateString的实现如下,我通过注释对里面的每行代码做了详细的说明。
static napi_value NAPI_Global_ConcatenateString(napi_env env, napi_callback_info info) {
// 定义变量存储从JS接收的参数
size_t argc = 2;
napi_value args[2];
// 获取JS传递的参数
napi_status status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to get callback info");
return NULL;
}
// 检查参数数量是否正确
if (argc < 2) {
napi_throw_error(env, NULL, "Expected 2 arguments");
return NULL;
}
// 检查第一个参数是否为字符串
napi_valuetype type;
status = napi_typeof(env, args[0], &type);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to check type of first argument");
return NULL;
}
if (type != napi_string) {
napi_throw_error(env, NULL, "First argument must be a string");
return NULL;
}
// 检查第二个参数是否为字符串
status = napi_typeof(env, args[1], &type);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to check type of second argument");
return NULL;
}
if (type != napi_string) {
napi_throw_error(env, NULL, "Second argument must be a string");
return NULL;
}
// 获取第一个字符串的长度
size_t len1;
status = napi_get_value_string_utf8(env, args[0], NULL, 0, &len1);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to get length of first string");
return NULL;
}
// 分配内存并获取第一个字符串内容
char* str1 = (char*)malloc(len1 + 1);
if (str1 == NULL) {
napi_throw_error(env, NULL, "Failed to allocate memory for first string");
return NULL;
}
status = napi_get_value_string_utf8(env, args[0], str1, len1 + 1, NULL);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to get first string value");
free(str1);
return NULL;
}
// 获取第二个字符串的长度
size_t len2;
status = napi_get_value_string_utf8(env, args[1], NULL, 0, &len2);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to get length of second string");
free(str1);
return NULL;
}
// 分配内存并获取第二个字符串内容
char* str2 = (char*)malloc(len2 + 1);
if (str2 == NULL) {
napi_throw_error(env, NULL, "Failed to allocate memory for second string");
free(str1);
return NULL;
}
status = napi_get_value_string_utf8(env, args[1], str2, len2 + 1, NULL);
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to get second string value");
free(str1);
free(str2);
return NULL;
}
// 分配内存存储拼接后的字符串
char* result = (char*)malloc(len1 + len2 + 1);
if (result == NULL) {
napi_throw_error(env, NULL, "Failed to allocate memory for result string");
free(str1);
free(str2);
return NULL;
}
// 执行字符串拼接
strcpy(result, str1);
strcat(result, str2);
// 释放临时字符串的内存
free(str1);
free(str2);
// 创建JS字符串并返回
napi_value return_value;
status = napi_create_string_utf8(env, result, len1 + len2, &return_value);
free(result); // 释放结果字符串的内存
if (status != napi_ok) {
napi_throw_error(env, NULL, "Failed to create return string");
return NULL;
}
return return_value;
}
验证js接口
- 我们将上面实现的js接口添加到
src/main/ets/pages/Index.ets文件中来验证其功能是否正常。 - 在
onClick回调中添加如下代码:
hilog.info(DOMAIN, 'testTag', 'Test NAPI aaa + bbb = %{public}s', testNapi.ConcatenateString("aaa", "bbb"));
- 编译,安装应用,点击Hello World,在log界面我们可以看到如下打印,说明接口功能正常:

总结
- 到这里我们已经初步掌握了napi的用法,想要更深层次了解napi,大家可以参考华为官方文档,写的非常详细:使用Node-API实现跨语言交互
参考文档
更多推荐


所有评论(0)