前语

  • JSB:JavaScript Binding,是Cocos Game的JS脚本与Native Engine的C++互相调用的映射绑定。留神这有差异与传统的JS Bridge,JSB具有更源码共享网高的Runtime功用;
  • 本文介绍JSB在Cocos游戏引擎结构中作用,如何将Native函数经过JSB绑定到Cocos Game让开发者调用;

1. Cocos2d结构中的JSB

1.1 JS-Binding与JS-Bridge

当时的悉数依据JavaScript开发的前端结构中,包含Cocos游戏、小程序、快应用、Weex、RN,都是运行在JS引擎上的,最典型的JS引擎便是源码编辑器编程猫下载Google开发的V8引擎,Cocos也是用的V8。而大部分的JS引擎都是依据C/C++开发的,所以必定存在JS与接口测验C/C++交互的特性,这一层常用的便是JS-Bridge,顾名思义便是JS跟Native互访的桥梁。
JS-Bridge最广泛的完毕办法便是经过PostMessage的办法,将JS需求拜访的内容以二进制数javascript菜鸟教程据发往Native,然后由Native进行解析,跟RPC调用相似。尽管这种办法JavaScript用力google枸杞来简单,但存在这很大的功用缺点javascript,由于需求不断对数据进行序列化及反序列源码时代化,所以只合适用在调度不频频的JS-Bridge。尽管小程序运用Pro源码交易网站源码to源码本钱Buf替代了JSON的解析,功用提google服务结构升了不少,带还是解决不了根本问题。
那么V8引擎本身也是依据C/C++开发的,它的内建特性如JSON、Dajavascript什么意思ta是怎google商铺样完毕的?也是选用P接口类型osgoogle地球tMessa源码时代ge这样的办法?我当然不可能接口协议搬石头砸自己的脚,这时候就要推接口测验面试题出JS-Binding了。JS-Binding运用了和V8内建函数相同的特性,将自界说的类、函数、变量等与JS绑定映射联络,使JS代码可做到相当于直接拜访C/C++代码。下面提到的JSB都指JS-Binding公积金

1.2 深度解析JSB

这儿假设都有Cocos游戏的开发经历,因此关于前端的特性不会做过多的介绍。先上图,再逐一分解:

1.2.1 Cocos游戏结构图。

(今天花了巨款买了EA的License,便是为了看到下面的图。)
【Cocos源码解析】Cocos2d结构中的JSB

1.2.2 剖析

  • main.js:开发者开发的游戏代码放在这儿,毕竟也是执行在Native的JS引擎里;
  • Audio/Image/GFX/Network:Cocogoogle空间s游戏引擎的音频、图片、GFX、网络等特性,这些特性前javascript高级程序设计端结构暴露出接口,具体完毕都是在Native引擎开发的;
  • ScriptEngine:Native引擎中的J工商银行S引擎,运google浏览器用了V8完毕。Cocos封装了无关具体JS引擎特性的接口JS Interface,现在业界广泛称为JSI;

这张图是Cocos游戏引擎的大致结构图,javascript:void(0)其间环绕JSB的特性进行了提取;从上图能源码码头够看出,JSB处于Native引擎中,当开发者在JS层需求运用如源码共享网音频特性时,对Audio政策的特色拜访或办法调用,都会经过JSB映射到初始化时就注入到JS引擎的Native政策。并由Native的音频特性完毕对应的访google空间问或调用,然后回调给JS的政策。比如在引擎初始化时,Native引擎会向前端注入jsb政策,并映射AudioEngine类:

bool jsb_register_global_源码本钱variables(se::Object *global) {
...
getOrCreatePlainOb接口是什么ject狗狗币_r("jsb", global, &__jsbObj); // C++往前端注入jsb政策
...
}
...
bool js_register_audio_宫颈癌疫苗AudioEngine(se::Obgoogle商铺ject* obj)
{
auto cls接口和抽象类的差异 = se::Class::create("源码编辑器编程猫下载Audi工商银行oEngine", obj, nullptr, nuJavaScriptllptr); // C++往前接口测验面试题端映射AudioEngine类
...
}

然后在JS结构侧就能够直接对jsb政策进行拜访AudioEnginjavascript菜鸟教程e的函数:

    playOneShot(volume) {
......
jsb.AudioEngine.play(this._url, false, volume); // JS调用AudioEngine办法
}

【Cocos源码解析】Cocos2d结构中的JSB

别的JSB注册进去的这些模块特性,尽管位处两地,却身在曹营心在汉,这他喵都是一一对应的映射联络的。当时的一些模块层级图大致如下:
【Cocos源码解析】Cocos2d结构中的JSB

1.3 C接口和抽象类的差异ocos2d源码解析JSB

先看JSB注入前端的流程图
【Cocos源码解析】Cocos2d结构中的JSB

  1. 首要要在Native层先完毕要注入的事务特性,Cocos2d供给了JSB事务模板作为悉数Native事务特性的进口,如:
// Native事务特性的进口
static bool js_audio_AudioEngine_play2d(se::State& s)
{
const auto& args = s.args();
size_t argcGoogle = args.sijavascript菜鸟教程ze();
CC_UNUSED bool ok = tgoogle空间rue;
if (argc == 1) {
HolderType<std::string,javascript true> arg0 = {};
ok &= sevalue_to_native(args[0], &arg0, nullptr);
SE_PRECONDITION2(ok, false, "js_audio_AudioEngine_play2d : E源码交易网站源码rror processing arguments");
int result = cc::AudioEngine:google空间:play2d(arg0.value());
ok &= nativevalue源码网站_tgoogle空间o_se(result, s.rval(), nullptr /*ctx*/);googleplay安卓版下载
SE_PRECONDITION2(ok, false, "j接口crc错误计数s_audio_AudioE接口测验面试题ngine_play2d : Error proce接口测验ssing arguments");
SE_HOLD_RETURN_VALUE(resu接口测验的流程和步骤lt, s.thisObjectGoogle(宫颈癌疫苗), s.rval());
return true;
}
...
}

进口函数有必要是静态域才华被拜访到,作用首要是为了从se::State& s解析出JS映射过来的入参,然后依据事务特性,传递给Native层的事务特性作为Go入参运用。
2. 完毕完事务特性后,Cocos2d供给了宏SE_BIND_FUNC将进口函数进行预绑定。留神此时仅仅完毕了界说,还未实在注javascript和java的差异入:

SE_BINJavaScriptD_FUNC(js_audio_AudioEngine_play2d) // 预绑定

SE_BIND_FUNC宏将事务进口函数拼接“Registry”后缀,并依据V8的Build-in内建特性,将JS引擎的函数模板绑定到事务特性进口函数。这种函javascript:void(0)数的形参共同都为:const vGo8::FunctionCallbackInfov8::Value&。
下面的代码中:ret = funcNamejavascript(state)句子便是调用了事务特性的进口函数,其上的句子是将V8的内建函数模板的参数解析成JSI的参数;其下的句子,是给内建函数模板设置返回值。

#define SE_BIND_F公积金借款UNC(funcName)                                                                        
void funcName##Registry(const v8::FunctionCallbackInfo<v8::Value> &_v8args) {                     
recordJSBInvoke(#funcName);                                                                   
booljavascript怎样读 ret = false;                                                                             
v8::Isol源码网ate *_isolate = _v8args.源码编辑器GetIsolate();                                                 
v8::HandleScope _hs(_isolate);                                                                
SE_UNUSED unsign接口协议ed argc = (unsigned)_v8args.Length();                                         
se::ValueArrjavascript面试题agoogle商铺y args;                                                                          
args.reserve(10);                                                                             
se::internal::jsToSeArgs(_v8args, &args);                                                     
void *nativeThisObject = se::internal::getPrivate(_isolat源码码头e, _公积金借款v8args.This());                  
se::State state(nativeThisObject, argoogle浏览器gs);                                                      
ret = funcName(state);                                                                        
if (!ret) {                                                                                   
SE_LOGE("[ERROR] Failed to invoke %s, location: %s:%dn", #funcName, __FILE__, __LINE__); 
}                                                                                             
se::internal::setReturnValue(state.rval(), _v8args);                                          
}
  1. 界说JSB的注册函数,指明要接口是什么将Native的哪个函数钩子注入到前端结构的哪个政策,注入的别号叫什么:
bool js_register_audio_源码共享网AudioEngine(se::Objec接口类型t* obj)
{
...
// 将Nativ源码e业javascript面试题务函数钩子js_audio_AudioEngine_play2d注入到前端政策obj,别号为play2d
clGos->defineStaticFunction("play2d", _SE(js_aud源码共享网io_AudioEngine_play2d));
...
}

_SE宏指明内建模板函数,正好跟前面SE_BIND_FUNC宏相同,都拼接了“Registry”后缀,才华保持模板函数名一接口协议起。其界说为:

define _SE(name) name##Registry
  1. 挂接JSB注册函数,Coco2d的Native引擎,在初始化时,会调用jsb_register_all_modules把悉数需求注入到前端结构的Native特性,都注入到googleplayJS引擎中。
bool jsb_register_all_modules() {
se::ScriptEngine *se = se::Sc源码网riptEngine::getInstance();
...
#if USE_AUDIO
se->addRegisterCallback(register_all_audio);
#endif
...
}
  1. 到此就算接口的作用注入完毕,之后只需能在前端的接口类型JS代码中,经过注入的别号拜访到对应的政策或许函数,即算完毕。
你鞋废了吗?
原创作品,转载请注明出处!
更多精彩,请持续注重!