HarmonyOS 使用napi方法返回一个对象,多次调用会闪退
代码如下:
Index.ets
import { hilog } from '@kit.PerformanceAnalysisKit';
import testNapi from 'libentry.so';
class DateTime {
constructor() {
this.year = 0;
this.month = 0;
this.day = 0;
this.hour = 0;
this.minute = 0;
this.second = 0;
this.milliseconds = 0;
this.utHourOffset = 0;
this.utMinuteOffset = 0;
}
year: number;
month: number;
day: number;
hour: number;
minute: number;
second: number;
milliseconds: number;
utHourOffset: number;
utMinuteOffset: number;
}
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(async () => {
// 返回复杂对象会崩溃
let ret = await testNapi.add(2, 3) as DateTime;
hilog.info(0x0020, 'testTag', 'year:%{public}d, month:%{public}d, day:%{public}d, hour:%{public}d',
ret.year, ret.month, ret.day, ret.hour);
// 返回简单对象不会崩溃
//let ret = await testNapi.add(2, 3) as DateTime;
//hilog.info(0x0020, 'testTag', 'ret:%{public}d', ret);
})
}
.width('100%')
}
.height('100%')
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
Index.d.ts
// 返回复杂对象会崩溃
export const add: (a: number, b: number) => Promise<object>;
// 返回简单对象不会崩溃
//export const add: (a: number, b: number) => Promise<number>;
- 1.
- 2.
- 3.
- 4.
- 5.
napi_init.cpp
#include "napi/native_api.h"
#include <cassert>
struct FSDateTime {
int year;
int month;
int day;
int hour;
int minute;
int second;
int milliseconds;
int UTHourOffset;
int UTMinuteOffset;
};
struct stRunTime {
int nStatus; // FR_SUCCESS代表成功, 负数代表失败
napi_async_work work;
napi_deferred deferred;
napi_ref napiRef;
stRunTime() : nStatus(0), work(nullptr), deferred(nullptr), napiRef(nullptr) {}
};
static napi_value fsDateTime2JsDateTime(napi_env env, const FSDateTime &fsDateTime) {
napi_value napiResult = nullptr, napiProperty = nullptr;
napi_create_object(env, &napiResult);
napi_create_uint32(env, fsDateTime.year, &napiProperty);
napi_set_named_property(env, napiResult, "year", napiProperty);
napi_create_uint32(env, fsDateTime.month, &napiProperty);
napi_set_named_property(env, napiResult, "month", napiProperty);
napi_create_uint32(env, fsDateTime.day, &napiProperty);
napi_set_named_property(env, napiResult, "day", napiProperty);
napi_create_uint32(env, fsDateTime.hour, &napiProperty);
napi_set_named_property(env, napiResult, "hour", napiProperty);
napi_create_uint32(env, fsDateTime.minute, &napiProperty);
napi_set_named_property(env, napiResult, "minute", napiProperty);
napi_create_uint32(env, fsDateTime.second, &napiProperty);
napi_set_named_property(env, napiResult, "second", napiProperty);
napi_create_uint32(env, fsDateTime.milliseconds, &napiProperty);
napi_set_named_property(env, napiResult, "milliseconds", napiProperty);
napi_create_int32(env, fsDateTime.UTHourOffset, &napiProperty);
napi_set_named_property(env, napiResult, "utHourOffset", napiProperty);
napi_create_uint32(env, fsDateTime.UTMinuteOffset, &napiProperty);
napi_set_named_property(env, napiResult, "utMinuteOffset", napiProperty);
return napiResult;
}
static void jsExecuteCallback(napi_env env, void *data) {
stRunTime *pRunTime = (stRunTime *)data;
pRunTime->nStatus = 0;
// 返回复杂对象会崩溃
FSDateTime fsDateTime = {1, 2, 3, 4, 5, 6, 7, 8, 9};
napi_value napiRet = fsDateTime2JsDateTime(env, fsDateTime);
// 返回简单对象不会崩溃
// napi_value napiRet;
// assert(napi_ok == napi_create_int32(env, 111, &napiRet));
assert(napi_ok == napi_create_reference(env, napiRet, 1, &pRunTime->napiRef));
}
static void jsCompleteCallback(napi_env env, napi_status status, void *data) {
stRunTime *pRunTime = (stRunTime *)data;
napi_value result = nullptr;
if (pRunTime->nStatus == 0) {
assert(napi_ok == napi_get_reference_value(env, pRunTime->napiRef, &result));
} else {
assert(napi_ok == napi_get_undefined(env, &result));
}
if (pRunTime->deferred != nullptr) {
if (pRunTime->nStatus == 0) {
assert(napi_ok == napi_resolve_deferred(env, pRunTime->deferred, result));
} else {
assert(napi_ok == napi_reject_deferred(env, pRunTime->deferred, result));
}
}
if (pRunTime->napiRef != nullptr) {
assert(napi_ok == napi_delete_reference(env, pRunTime->napiRef));
}
assert(napi_ok == napi_delete_async_work(env, pRunTime->work));
delete pRunTime;
pRunTime = nullptr;
}
static napi_value Add(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
napi_valuetype valuetype0;
napi_typeof(env, args[0], &valuetype0);
napi_valuetype valuetype1;
napi_typeof(env, args[1], &valuetype1);
double value0;
napi_get_value_double(env, args[0], &value0);
double value1;
napi_get_value_double(env, args[1], &value1);
stRunTime *pRunTime = new stRunTime();
napi_value napiRet = nullptr;
assert(napi_ok == napi_create_promise(env, &pRunTime->deferred, &napiRet));
napi_value resourceName = nullptr;
assert(napi_ok == napi_create_string_utf8(env, "add", NAPI_AUTO_LENGTH, &resourceName));
assert(napi_ok == napi_create_async_work(env, nullptr, resourceName, jsExecuteCallback, jsCompleteCallback,
(void *)pRunTime, &pRunTime->work));
assert(napi_ok == napi_queue_async_work(env, pRunTime->work));
return napiRet;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void *)0),
.reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
HarmonyOS
赞
收藏 0
回答 1
相关问题
HarmonyOS 使用Webview会闪退
735浏览 • 1回复 待解决
HarmonyOS Native C函数中有多线程交互,用napi调用会闪退
994浏览 • 1回复 待解决
HarmonyOS 在应用启动的时候调用一个ets里面引用了上下文 启动会闪退
635浏览 • 1回复 待解决
HarmonyOS napi如何传递一个对象,然后C++侧调用这个对象内部的回调方法
1102浏览 • 1回复 待解决
Napi中的方法如何返回一个数组类型?
1330浏览 • 1回复 待解决
HarmonyOS number toFixed方法闪退
919浏览 • 1回复 待解决
HarmonyOS 利用BuilderParam将组件传值后,调用方法闪退
836浏览 • 1回复 待解决
HarmonyOS 页面返回时应用闪退报错
1684浏览 • 1回复 待解决
HarmonyOS Promise调用promptAction.showToast会闪退,请问要如何解决
608浏览 • 1回复 待解决
开发一个APP,它包含了napi常见的同步调用方法
1424浏览 • 1回复 待解决
打开图库应用时偶尔会闪退
3366浏览 • 0回复 待解决
HarmonyOS 在page页面读取router带过来的对象参数,调用其成员方法时程序闪退
606浏览 • 1回复 待解决
HarmonyOS调用 gattClient.off('BLECharacteristicChange') 项目闪退
1151浏览 • 0回复 待解决
HarmonyOS napi C++侧怎么通过一个“ClassName” 初始化一个ArkTS的对象
1178浏览 • 1回复 待解决
HarmonyOS promptAction.showToast在多次调用时候会多次生成
529浏览 • 1回复 待解决
HarmonyOS promptAction.showToast在多次调用时候会多次生成?
647浏览 • 0回复 待解决
如何通过 napi 获取一个 C++ map 类型的对象
2507浏览 • 1回复 待解决
HarmonyOS C++ 调用 ets 层函数报错闪退
971浏览 • 1回复 待解决
HarmonyOS 如何返回上一个界面?类似 finish() 方法
666浏览 • 1回复 待解决
HarmonyOS 跳转应用商店到指定应用方法闪退
736浏览 • 1回复 待解决
HarmonyOS 目前H5代码,调用uniapp.postMessage方法,app闪退
732浏览 • 1回复 待解决
HarmonyOS 分享组件无法正常使用,闪退
732浏览 • 1回复 待解决
鸿蒙 IPC 开发中,服务端返回的 Stub 对象里的 onConnect 方法为啥要返回一个新的 Stub 对象?
331浏览 • 1回复 已解决
HarmonyOS应用闪退问题
1637浏览 • 1回复 待解决
HarmonyOS 使用AudioCapturer录音过程中闪退
1124浏览 • 1回复 待解决
多线程安全问题。
napi_create_async_work的第四个参数jsExecuteCallback,其是在业务线程执行,jsExecuteCallback函数在调用fsDateTime2JsDateTime和napi_create_reference函数时,env是主线程的env,创建的napi_value和napi_ref类型的变量都是在子线程中,所以会崩溃。
问题的分析定位,请参考方舟多线程检测:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-multi-thread-check-0000001919872114-V5