JSB(Javascript Binding)
JSB 是第二座桥,它与 JNI 类似,是提供 Native 层与 Javascript 层互相访问的一种方式,支持双向调用。
上面一章节提到了普通的 Android 程序架构,下面的是 Cocos 程序的架构,它是这样的:
在 Java 之上又通过 JNI 回到了 Cocos 的 Native 层,此层是通过动态链接库.so 加载的。然后再经过一个 JSB 的桥与 Javascript 进行交互。游戏则是使用 Javascript 编写的。
JSB 有好几种,有 Mozilla 家的 SpiderMonkey 和 Google 家的 V8,最新的 iOS 里则用到了 Apple 自家的 JSB 接口。使用哪种 JSB 接口主要取决于使用哪种 Javascript 虚拟机。
排除掉各种 JS 虚拟机的不同,Cocos 为我们提供了统一的接口,让我们可以使用。它能实现 Javascript 中的一个方法与一个 C 方法进行绑定。在 Javascript 中调用该方法时,则在 C++中被绑定的方法会被调用。
1、Javascript 调用 C++
如果我们在 C++中看见这样的函数名 js*
1 | static bool js_cocos2dx_FileUtils_addSearchPath(se::State& s) |
这时一段典型的 JSB 代码,通过函数名我们就知道了这个 JSB 绑定的是 FileUtils 的 addSearchPath 方法。
addSearchPath 是个重载函数,一个有 1 参数,一个有 2 参数。我们可以看到 JSB 中是以 逻辑 来区分函数重载的。
乍一看,JSB 也辣么变态,1 行代码变成 27 行。如果我只有一个函数绑定 JSB 还好,如果我有成百上千和函数要绑定,岂不是这辈子都要搭里面了?Noooooo…
好在 Cocos 又提供的方案,就是自动生成 JSB 代码。只需要简(bìng)单(bù)配置一个配置文件,然后让生成脚本跑一下,那成百上千的 JSB 绑定函数就变出来了。
在我们的项目中,我将这个工具放在了 tools/bindings-generator 下。配置文件是 test/test.ini,生成脚本是 test/test.py。
不细讲了,自己看吧。
2、C++ 调用 Javascript
不推荐使用 C++调用 Javascript,因为需要明确地写明方法名来找到该 JS 方法并调用。而 C++是编译语言不支持热更,Javascript 则是脚本语言可以作为资源进行热更新。这很容易造成 Js 中的方法名修改后导致调用失效。
解决方案就是将 Js 方法作为参数传入 C++中,在 C++中调用该注册方法。上面提到的 bindings-generator 支持生成将函数作为参数的代码,好好利用吧。