文档管理中心
FAQ应用框架开发NDK开发NDK开发C++侧使用ArrayBuffer接收Float数组时异常

C++侧使用ArrayBuffer接收Float数组时异常

问题现象

C++端要如何接收number[]数组,数组里保存的是Float类型,使用napi_get_arraybuffer_info接口接收,获取到的status是napi_arraybuffer_expected。

背景知识

使用Node-API接口进行Array相关开发:使用Node-API接口进行数组相关开发时,涉及的基本概念主要包括数组的创建、访问、修改、遍历以及与数组相关的操作。这些概念对于理解如何在Node-API模块中与ArkTS数组交互非常重要。

解决方案

ArkTS中的number数组是普通数组类型,而ArrayBuffer是二进制缓冲区类型,二者在NAPI层不兼容。

方案一:基于ArrayBuffer接收Float数组:

需要将数组类型改为Float32Array类型进行传递。使用napi_get_typedarray_info获取给定TypedArray的各种属性。

  • C++侧代码:
    收起
    自动换行
    深色代码主题
    复制
    1. static napi_value TransmitByTypedArray(napi_env env, napi_callback_info info)
    2. {
    3. // 获取ArkTS侧传入的参数
    4. size_t argc = 2;
    5. napi_value args[2] = {nullptr};
    6. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    7. // 定义napi_get_typedarray_info所需参数
    8. void *data;
    9. napi_typedarray_type type;
    10. size_t byteOffset, length;
    11. napi_value arraybuffer;
    12. // 调用接口napi_get_typedarray_info获得TypedArray类型数据的信息
    13. napi_get_typedarray_info(env, args[0], &type, &length, &data, &arraybuffer, &byteOffset);
    14. float* displayArr = (float*)data;
    15. float a = displayArr[0];
    16. float b = displayArr[1];
    17. OH_LOG_INFO(LOG_APP, "First element in TypedArray: %{public}f", a);
    18. OH_LOG_INFO(LOG_APP, "Second element in TypedArray: %{public}f", b);
    19. return NULL;
    20. }
  • 接口声明:
    收起
    自动换行
    深色代码主题
    复制
    1. export const transmitByTypedArray: <T>(typeArray: T, b: number) => void;
  • ArkTS侧代码:

    此处使用了Button组件,点击触发接收数据,并打印日志。

    收起
    自动换行
    深色代码主题
    复制
    1. Button('use TypedArray')
    2. .onClick(() => {
    3. let fa: Float32Array = new Float32Array([1.10, 2.22222, 3.69, 4.5]);
    4. testNapi.transmitByTypedArray(fa, 4);
    5. })

方案二:仍使用number[]接收Float数组:

由于ArkTS中number本质上为Double类型、应显式转换为Float类型,使用循环语句逐个提取Float元素。

  • C++侧代码:
    收起
    自动换行
    深色代码主题
    复制
    1. static napi_value TransmitByNumber(napi_env env, napi_callback_info info)
    2. {
    3. // 获取ArkTS侧传入的参数
    4. size_t argc = 2;
    5. napi_value args[2] = {nullptr};
    6. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    7. // 判断是否为数组
    8. bool isArr = false;
    9. napi_is_array(env, args[0], &isArr);
    10. if (!isArr) {
    11. napi_throw_error(env, nullptr, "Argument should be an object of type array");
    12. return NULL;
    13. }
    14. // 获取数组长度
    15. uint32_t arrayLength;
    16. napi_get_array_length(env, args[0], &arrayLength);
    17. // 循环语句逐一提取number[]元素
    18. std::vector<float> floatData;
    19. for (uint32_t i = 0; i < arrayLength; i++) {
    20. napi_value element;
    21. napi_get_element(env, args[0], i, &element);
    22. double val;
    23. napi_get_value_double(env, element, &val); // 转换为double
    24. floatData.push_back(static_cast<float>(val)); // 显式转为float
    25. }
    26. float a = floatData[0];
    27. float b = floatData[1];
    28. OH_LOG_INFO(LOG_APP, "First element in number[]: %{public}f", a);
    29. OH_LOG_INFO(LOG_APP, "Second element in number[]:%{public}f", b);
    30. return NULL;
    31. }
  • 接口声明:
    收起
    自动换行
    深色代码主题
    复制
    1. export const transmitByNumber: <T>(arr: Array<T>, index: number) => void;
  • ArkTS侧代码:

    此处使用了Button组件,点击触发接收数据,并打印日志。

    收起
    自动换行
    深色代码主题
    复制
    1. Button('use number[]')
    2. .onClick(() => {
    3. let na: number[] = [1.10, 2.22222, 3.69, 4.5];
    4. testNapi.transmitByNumber(na, 4);
    5. })

完整示例参考如下:

  • C++侧代码:
    收起
    自动换行
    深色代码主题
    复制
    1. /*
    2. * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
    3. * Licensed under the Apache License, Version 2.0 (the "License");
    4. * you may not use this file except in compliance with the License.
    5. * You may obtain a copy of the License at
    6. *
    7. * http://www.apache.org/licenses/LICENSE-2.0
    8. *
    9. * Unless required by applicable law or agreed to in writing, software
    10. * distributed under the License is distributed on an "AS IS" BASIS,
    11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12. * See the License for the specific language governing permissions and
    13. * limitations under the License.
    14. */
    15. #include "napi/native_api.h"
    16. #include "hilog/log.h"
    17. #include <cstddef>
    18. #include <vector>
    19. #undef LOG_DOMAIN
    20. #undef LOG_TAG
    21. #define LOG_DOMAIN 0x0000 // 全局domain宏,标识业务领域
    22. #define LOG_TAG "MY_TAG" // 全局tag宏,标识模块日志tag
    23. static napi_value TransmitByTypedArray(napi_env env, napi_callback_info info)
    24. {
    25. // 获取ArkTS侧传入的参数
    26. size_t argc = 2;
    27. napi_value args[2] = {nullptr};
    28. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    29. // 定义napi_get_typedarray_info所需参数
    30. void *data;
    31. napi_typedarray_type type;
    32. size_t byteOffset, length;
    33. napi_value arraybuffer;
    34. // 调用接口napi_get_typedarray_info获得TypedArray类型数据的信息
    35. napi_get_typedarray_info(env, args[0], &type, &length, &data, &arraybuffer, &byteOffset);
    36. float* displayArr = (float*)data;
    37. float a = displayArr[0];
    38. float b = displayArr[1];
    39. OH_LOG_INFO(LOG_APP, "First element in TypedArray: %{public}f", a);
    40. OH_LOG_INFO(LOG_APP, "Second element in TypedArray: %{public}f", b);
    41. return NULL;
    42. }
    43. static napi_value TransmitByNumber(napi_env env, napi_callback_info info)
    44. {
    45. // 获取ArkTS侧传入的参数
    46. size_t argc = 2;
    47. napi_value args[2] = {nullptr};
    48. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    49. // 判断是否为数组
    50. bool isArr = false;
    51. napi_is_array(env, args[0], &isArr);
    52. if (!isArr) {
    53. napi_throw_error(env, nullptr, "Argument should be an object of type array");
    54. return NULL;
    55. }
    56. // 获取数组长度
    57. uint32_t arrayLength;
    58. napi_get_array_length(env, args[0], &arrayLength);
    59. // 循环语句逐一提取number[]元素
    60. std::vector<float> floatData;
    61. for (uint32_t i = 0; i < arrayLength; i++) {
    62. napi_value element;
    63. napi_get_element(env, args[0], i, &element);
    64. double val;
    65. napi_get_value_double(env, element, &val); // 转换为double
    66. floatData.push_back(static_cast<float>(val)); // 显式转为float
    67. }
    68. float a = floatData[0];
    69. float b = floatData[1];
    70. OH_LOG_INFO(LOG_APP, "First element in number[]: %{public}f", a);
    71. OH_LOG_INFO(LOG_APP, "Second element in number[]:%{public}f", b);
    72. return NULL;
    73. }
    74. EXTERN_C_START
    75. static napi_value Init(napi_env env, napi_value exports)
    76. {
    77. napi_property_descriptor desc[] = {
    78. {"transmitByTypedArray", nullptr, TransmitByTypedArray, nullptr, nullptr, nullptr, napi_default, nullptr },
    79. {"transmitByNumber", nullptr, TransmitByNumber, nullptr, nullptr, nullptr, napi_default, nullptr}
    80. };
    81. napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    82. return exports;
    83. }
    84. EXTERN_C_END
    85. static napi_module demoModule = {
    86. .nm_version = 1,
    87. .nm_flags = 0,
    88. .nm_filename = nullptr,
    89. .nm_register_func = Init,
    90. .nm_modname = "entry",
    91. .nm_priv = ((void*)0),
    92. .reserved = { 0 },
    93. };
    94. extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
    95. {
    96. napi_module_register(&demoModule);
    97. }
  • 接口声明:
    收起
    自动换行
    深色代码主题
    复制
    1. export const transmitByTypedArray: <T>(typeArray: T, b: number) => void;
    2. export const transmitByNumber: <T>(arr: Array<T>, index: number) => void;
  • ArkTS侧代码:
    收起
    自动换行
    深色代码主题
    复制
    1. import testNapi from 'libentry.so';
    2. @Entry
    3. @Component
    4. struct Index {
    5. build() {
    6. Row() {
    7. Column({space: 10}) {
    8. Button('use TypedArray')
    9. .onClick(() => {
    10. let fa: Float32Array = new Float32Array([1.10, 2.22222, 3.69, 4.5]);
    11. testNapi.transmitByTypedArray(fa, 4);
    12. })
    13. .width('50%')
    14. Button('use number[]')
    15. .onClick(() => {
    16. let na: number[] = [1.10, 2.22222, 3.69, 4.5];
    17. testNapi.transmitByNumber(na, 4);
    18. })
    19. .width('50%')
    20. }
    21. .width('100%')
    22. }
    23. .height('100%')
    24. }
    25. }
在 FAQ 中进行搜索
请输入您想要搜索的关键词