NPAPI 开发, C++跨线程回调JS函数

通常,在插件中如果要调用JS的函数可以使用NPN_InvokeDefault()来实现,但是调用NPN_InvokeDefault必须要在JS的调用栈中(JS线程)。

    比如,JS有两个函数j-a,j-b,在C++中有函数c-a。那么如果要在c-a中使用NPN_InvokeDefault调用j-b,则必须是j-a调用了c-a,形成j-a -> c-a -> j-b这样的调用链路。

以上的C++调用JS的方法显然不能满足多数时候的需求,因为我们很多时候会执行异步操作,比如如果c-a要执行很长时间,我们不可能让j-a等着c-a执行完,这样的话UI就会阻塞。所以通常我们的做法是在j-a中通知c-a干活(c-a在别的线程中),当c-a完成任务后调用j-b返回结果,这个时候,就需要用到NPN_PluginThreadAsyncCall()了。从名字就可以看出来这是个跨线程异步调用的方法。

   由于这个东西的资料比较少(我当时是中文没搜到然后英文搜索然后搞到个文档总结完成的),所以在这里做个总结希望能帮助大家节省时间。


NPN_PluginThreadAsyncCall()的使用方法比较简单,就相当于做几个配置,将NPN_PluginThreadAsyncCall()的声明与NPAPI框架提供的功能做一个挂接。

1.其实在npapi.h中已经有NPN_PluginThreadAsyncCall()的声明,但没有定义,所以,我们首先给它做定义:

在npn_gate.cpp中添加NPN_PluginThreadAsyncCall()函数定义

void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void *), void *userData)
{
     NPNFuncs.pluginthreadasynccall(instance, func, userData);
}


2.大家应该知道NPNFuncs是一个结构体,其实pluginthreadasynccall是它一个函数指针(定义在npfunctions.h),既然要用这个指针,那么肯定需要给它赋值。所以,这一步我们给NPNFuncs.pluginthreadasynccallf赋值,在np_entry.cpp的NP_Initialize()函数中添加对NPNFuncs.pluginthreadasynccallf的赋值

NPNFuncs.pluginthreadasynccall   = pFuncs->pluginthreadasynccall;

其中pFuncs 和 NPNFuncs 是同一个类型的结构体(当然,pFuncs是这种类型的结构体的指针),NP_Initialize()函数中对NPNFuncs成员 的所有赋值操作就等于是将pFuncs所指向的结构体的内容存储在了NPNFuncs中(当然是选择性的复制,不然就memecpy了)。而看起来pFuncs 则是来自于NPAPI框架的。


从上诉的情况看来,其实一开始NPAPI框架在NP_Initialize()初始化的时候是把所有的功能都带进来的(通过pFuncs参数带进来),但是给NPNFuncs赋值的过程中会选择性的屏蔽一些不需要的功能。而我们需要使用更多功能的时候就需要按照以上的方法做挂接(即将pFuncs 的功能赋值到NPNFuncs,并且为NPNFuncs的该功能函数指针定义个调用接口函数如NPN_PluginThreadAsyncCall。而且通常来说这个接口函数在npapi.h中已经声明)。


根据以上步骤就完成了 NPN_PluginThreadAsyncCall的挂接,那么下面我们来看看这个函数怎么使用。

可以看到其函数原型为void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void *), void *userData),其中参数instance就不说了,会用NPN_InvokeDefault

你就知道。 而参数func则是你期望的一个能够调用JS函数的函数,通常组成为

func()

{

   ... ...

  NPN_InvokeDefault(instance, JS回调函数在本地的保存,参数,返回值)

   ... ...

}

第三个参数是传递给func的参数


为了让观众更直观的理解,我把我的代码贴出来(当然代码里因为使用类,含有一些私有变量,所以并不是func里面就调用NPN_InvokeDefault了,而是经过了一次拆包过程)

int PluginObject::CallJsFunAsync()//这是一个封装,供类对象里别的地方使用。其中NPN_PluginThreadAsyncCall()的第三个参数为该对象
{
     NPN_PluginThreadAsyncCall(npp, PluginObject::AsyncCallJsFun, this);
     return 0;
}


void PluginObject::AsyncCallJsFun(void *param)//NPN_PluginThreadAsyncCall()的第二个参数
{
     if(!param)
     {
          return ;
     }

     PluginObject* obj = static_cast<PluginObject*>(param);//将参数还原为类对象,并调用类对象的方法。
 
     obj->CallJsFun(obj->GetPicNameAndPath());
}


int PluginObject::CallJsFun(char *pStr)//在这个函数里最终调用JS的函数(通过NPN_InvokeDefault)
{
     int iRev = 0;

     if (m_pJSCallbackFunObj != NULL && strlen(pStr) < FILE_PATH_LEN)
     {
          NPVariant result;

          // 转换参数列表
          NPVariant relements[1];
          char callbackParam[FILE_PATH_LEN] = "";
          strcpy(callbackParam, pStr);
          STRINGZ_TO_NPVARIANT(callbackParam, relements[0]);
  
          // 调ì用JS函数  

          BOOL ret = NPN_InvokeDefault(npp, m_pJSCallbackFunObj, relements, 1, &result); 
          NPN_ReleaseVariantValue(&result);
     }

     return iRev;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值