HarmonyOS ArkTS调用Native接口机制咨询

有份代码运行顺序是这样的,应用层连续调这两个函数:

ret = this.mediaPlayerObj.RegisterCallback(this.cb);  
ret = this.mediaPlayerObj.StartPlay(plIn); 

底层调用:

napi_value MediaPlayerNapi::RegisterCallback(napi_env env, napi_callback_info info){ 
  size_t requireArgc = 1; 
  size_t argc = 1; 
  napi_value args[1] = {0}; 
  napi_value thisVar = nullptr; 
  void *data = nullptr; 
  napi_get_cb_info(env, info, &argc, args, &thisVar, &data); 
  MediaPlayerNapi *mediaPlayer = nullptr; 
  napi_unwrap(env, thisVar, (void **)&mediaPlayer); 
  int32_t ret=-1; 
  if (mediaPlayer->mMediaPlayerPtr != nullptr) { 
    ret = mediaPlayer->mMediaPlayerPtr->RegistCallback(mediaPlayer); 
    napi_create_reference(env, args[0], 1, &(mediaPlayer->callbackObjectRef)); 
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", 
      "MediaPlayerNapi::RegisterCallback time:%{public}d", clock()); 
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", 
      "MediaPlayerNapi::RegisterCallback ret:%{public}d", ret); 
  } 
  else{ 
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", 
      "MediaPlayerNapi::RegisterCallback  mediaPlayer->mMediaPlayerPtr is nullptr"); 
  } 
  napi_value res; 
  napi_create_int32(env, ret, &res); 
  return res; 
}

该函数注册回调,将ArkTS层传递进来的回调对象进行了napi_create_reference保存,并利用clock()函数输出此时的时刻;

napi_value MediaPlayerNapi::StartPlay(napi_env env, napi_callback_info info){ 
  size_t requireArgc = 1; 
  size_t argc = 1; 
  napi_value args[1] = {0}; 
  napi_value thisVar = nullptr; 
  void *data = nullptr; 
  napi_get_cb_info(env, info, &argc, args, &thisVar, &data); 
  MediaPlayerNapi *mediaPlayer = nullptr; 
  napi_unwrap(env, thisVar, (void **)&mediaPlayer); 
  nog::PlayerInfo playerInfo; 
  ExchangePlayerInfo(env,args[0],playerInfo); 
  int ret = mediaPlayer->mMediaPlayerPtr->StartPlay(playerInfo); 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", 
    "MediaPlayerNapi::StartPlay begin ret:%{public}d", ret); 
  napi_value res; 
  napi_create_int32(env,ret, &res); 
  return res; 
}

该函数开始播放播放器,调用了so接口,之后便会有回调上来,so底层回调上来后,记录回调的时刻:

void MediaPlayerNapi::Onloading(){ 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", "MediaPlayerNapi::Onloading time:%{public}d",clock()); 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", "MediaPlayerNapi::Onloading"); 
  if(callbackObjectRef != nullptr  && playerStatus){ 
    napi_value Onloading; 
    napi_status status; 
    napi_value callbackObject; 
    napi_get_reference_value(myEnv, callbackObjectRef, &callbackObject); 
    if(napi_ok != (status = napi_get_named_property(myEnv, callbackObject, "Onloading", &Onloading))){ 
      OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", "napi_get_named_property error"); 
      return; 
    }; 
    CallbackContext *asyncContext = new CallbackContext(); 
    asyncContext->env = myEnv; 
    if(napi_ok != (napi_create_reference(myEnv, Onloading, 1, &asyncContext->callbackRef))){ 
      OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "MediaPlayerNapi", "napi_create_reference error"); 
      return; 
    }; 
    asyncContext->argc = 0; 
    asyncContext->callbackObjectRef = callbackObjectRef; 
    uv_queue_work_fun(asyncContext, myEnv); 
  } 
}

发现回调onloading的时刻比之前registercallback还早。导致反复按顺序调这两个应用层函数时,有可能出现onloading崩溃,崩溃的报错显示,在我对之前registercallback传递下来的对象进行一些属性拉取(napi_get_named_property,napi_create_reference),方法调用时会崩溃。是不是可以认为此时registercallback传递下来的对象尚未在js中可能未完成创建,导致回调上来时无法找到,但应用层是顺序调用的,理论上调用StartPlay时,registercallback已经将该对象传递下来并完成了。又或者说,Native层的机制导致即使开始执行StartPlay了,但是registercallback过程要创建的这种js桥接并不一定完成?

HarmonyOS
2024-08-27 10:33:26
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
FengTianYa

1.RegisterCallback函数中,引用保存的是:

mediaPlayer->callbackObjectRef  
napi_create_reference(env, args[0], 1, &(mediaPlayer->callbackObjectRef)); 

2.Onloading函数中,是通过callbackObjectRef保存的,需要判断callbackObjectRef是否与mediaPlayer->callbackObjectRef是同一个引用。

if(callbackObjectRef != nullptr && playerStatus){ 
  napi_value Onloading; 
  napi_status status; 
  napi_value callbackObject; 
  napi_get_reference_value(myEnv, callbackObjectRef, &callbackObject);

3.Onloading函数中,Onloading是业务线程的处理函数,api_get_reference_value(myEnv, callbackObjectRef, &callbackObject);这个语句不是在myEnv环境变量生成的线程中,获取napi_value,作用域不一样,会引起崩溃,后面的 napi_get_named_property等等napi函数调用都存在作用域不一致情况请参考使用Node-API接口进行线程安全开发:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/use-napi-thread-safety-0000001774280466-V5里面介绍了,可以返回ArkTS层。

分享
微博
QQ
微信
回复
2024-08-27 17:22:06
相关问题
Native调用ArkTS侧类函数
828浏览 • 1回复 待解决
HarmonyOS napi 接口线程安全咨询
210浏览 • 1回复 待解决
arkts能否直接调用nodejs的接口
1706浏览 • 1回复 待解决
Native调用ArkTS的全局普通方法
753浏览 • 1回复 待解决
HarmonyOS如何调用http/https接口?
10109浏览 • 3回复 已解决
ArkTS异步机制与执行顺序
1091浏览 • 1回复 待解决
HarmonyOS ArkTS注册Native C函数监听
215浏览 • 1回复 待解决
HarmonyOS ArkTS接口回调的案例
251浏览 • 1回复 待解决
arkts侧hashmap转为native
818浏览 • 1回复 待解决
Native如何调ArkTS的方法
2047浏览 • 1回复 待解决
有没有调用日历的接口?
6188浏览 • 1回复 待解决
ArkTS语法咨询的问题有懂得吗?
2524浏览 • 1回复 待解决