前语
- 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,便是为了看到下面的图。)
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办法
}
别的JSB注册进去的这些模块特性,尽管位处两地,却身在曹营心在汉,这他喵都是一一对应的映射联络的。当时的一些模块层级图大致如下:
1.3 C接口和抽象类的差异ocos2d源码解析JSB
- 首要要在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);
}
- 界说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
- 挂接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
...
}
- 到此就算接口的作用注入完毕,之后只需能在前端的接口类型JS代码中,经过注入的别号拜访到对应的政策或许函数,即算完毕。