【cocos2d-x从c++到js】JS与C++的交互1——JS代码调用C++代码

【cocos2d-x从c++到js】JS与C++的交互1——JS代码调用C++代码,第1张

概述我们要通过SpiderMonkey引擎的注册接口,向SpiderMonkey注册相应的从C++到JS的绑定函数,这些函数用于把JS函数调用代码转换成对应C++函数调用来执行。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //在AppDelegate::applicationDidFinishLaunching函数中      ScriptingC

我们要通过SpIDerMonkey引擎的注册接口,向SpIDerMonkey注册相应的从C++到Js的绑定函数,这些函数用于把Js函数调用代码转换成对应C++函数调用来执行。


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //在AppDelegate::applicationDIDFinishLaunching函数中 Scriptingcore* sc = Scriptingcore::getInstance(); sc->addRegisterCallback(register_all_cocos2dx); sc->addRegisterCallback(register_all_cocos2dx_extension); sc->addRegisterCallback(register_cocos2dx_Js_extensions); sc->addRegisterCallback(register_all_cocos2dx_extension_manual); sc->addRegisterCallback(Jsb_register_chipmunk); sc->addRegisterCallback(JsB_register_opengl); sc->addRegisterCallback(Jsb_register_system); sc->addRegisterCallback(MinXmlhttpRequest::_Js_register); sc->addRegisterCallback(register_Jsb_websocket); sc->addRegisterCallback(register_all_cocos2dx_builder); sc->addRegisterCallback(register_CCBuilderReader); sc->addRegisterCallback(register_all_cocos2dx_gui); sc->addRegisterCallback(register_all_cocos2dx_gui_manual); sc->addRegisterCallback(register_all_cocos2dx_studio); sc->addRegisterCallback(register_all_cocos2dx_studio_manual); sc->addRegisterCallback(register_all_cocos2dx_spine);


可以看到上面导入了Cocos2d-x的各种库,核心库,扩展,opengl,物理引擎,websocket,CCB等等等等。

下面我们说Js代码如何调用C++代码。

首先,在创建Js对象的时候,也会创建一个对应的C++对象。换句话说,Js对象是和C++对象一一对应的(当然必须是引擎支持的,而且绑定了接口的)。然后,在Js对象执行函数时,发生了什么呢?SpIDerMonkey引擎会通过注册的接口,找到对应的C++对象,调用该对象上对应的C++函数。

换句话说,如果有下面的Js代码:

2 var node = cc.Node.create(); node.setVisible( false );

那么经过SpIDerMonkey执行后,会调用下面的代码:

auto node = CCNode::create(); node->setVisible( false 当然,SpIDerMonkey远远还不止干了这些,还做了很多事,比如绑定和查找Js和C++对象的对应关系,包装参数为对应类型,类型安全检查,返回值包装等等。要知道他干了些什么,直接看引擎代码是更好的选择。

在Cocos2d-x 3.0版的引擎中,引擎目录结构进行了大规模重构。

两个脚本语言被放到一个类似的目录中。其中auto-generated/Js-bindings文件夹是gxx-generator工具自动生成的所有C++绑定Js代码。而JavaScript/bingdings文件夹是手写的绑定代码,因为工具无法做到完全自动绑定,所以必须有一部分手写的(脚本语言都是这样,习惯就好了,谢谢)。

好,我们继续找刚才说的源代码。打开Jsb_cocos2dx_auto.cpp

19 JsBool Js_cocos2dx_Node_create(jscontext *cx,uint32_t argc,Jsval *vp) { if (argc == 0) { cocos2d::Node* ret = cocos2d::Node::create(); Jsval Jsret = JsVAL_NulL; do { (ret) { Js_proxy_t *proxy = Js_get_or_create_proxy<cocos2d::Node>(cx,(cocos2d::Node*)ret); Jsret = OBJECT_TO_JsVAL(proxy->obj); } else { Jsret = JsVAL_NulL; } while (0); Js_SET_RVAL(cx,vp,Jsret); return Js_TRUE; } Js_ReportError(cx, "Js_cocos2dx_Node_create : wrong number of arguments" ); Js_FALSE; }

这就是cc.Node.create()执行时,底层C++跑的代码。所有的通过Js调用C++的代码都与这个形式非常一致,首先看函数接口:

第一个参数jscontext *cx是Js的上下文

第二个参数uint32_t argc是Js代码中的参数个数,在这个里argc==0

第三个参数Jsval *vp是Js代码中的具体参数

继续分析

1 cocos2d::Node* ret = cocos2d::Node::create();

这个代码再熟悉不过了,标准的Cocos2d-x静态工场生成对象的代码

Jsval Jsret = JsVAL_NulL;

Jsval Jsret是这个函数的返回值,这是表示的是一个Js对象

Jsret = OBJECT_TO_JsVAL(proxy->obj);

@H_419_376@注意这个模板函数,get_or_create,这就是把Js对象和C++对象绑到一起的函数。他非常重要,注意Js和C++对象是一一对应关系,理解这个特效,有助于我们利用Js语言的动态性进行更方便的编程。绑完之后,下面那个函数是用于获得返回值。

最后,函数都要返回一个JsBool,表面这个函数执行是否成功。如果返回Js_FALSE,还会通过Js_ReportError打印一条报错信息。@H_419_376@注意!脚本语言有一个特点,如果函数运行失败了,则该函数后面的函数(在同一作用域中的)都会跳过执行。


继续看下一个函数

19 JsBool Js_cocos2dx_Node_setVisible(jscontext *cx,Jsval *vp) { Jsval *argv = Js_ARGV(cx,vp); JsBool ok = Js_TRUE; JsObject *obj = Js_THIS_OBJECT(cx,vp); Js_proxy_t *proxy = Jsb_get_Js_proxy(obj); cocos2d::Node* cobj = (cocos2d::Node *)(proxy ? proxy->ptr : NulL); JsB_PRECONDITION2( cobj,cx,Js_FALSE, "Js_cocos2dx_Node_setVisible : InvalID Native Object" ); if (argc == 1 ) { JsBool arg0; ok &= Js_ValuetoBoolean(cx,argv[ 0 ],&arg0); JsB_PRECONDITION2(ok,monospace!important; Font-size:1em!important; min-height:inherit!important; color:blue!important">"Js_cocos2dx_Node_setVisible : Error processing arguments" ); cobj->setVisible(arg0); return Js_TRUE; } "Js_cocos2dx_Node_setVisible : wrong number of arguments: %d,was expecting %d" ,argc, ); Js_FALSE; 这个函数和前一个函数的区别是,这个函数有参数,并且他是一个类成员函数(上一个是类静态函数),所以,这里要有this指针。

6 JsBool ok = Js_TRUE;
Js_proxy_t *proxy = Jsb_get_Js_proxy(obj); cocos2d::Node* cobj = (cocos2d::Node *)(proxy ? proxy->ptr : NulL); "Js_cocos2dx_Node_setVisible : InvalID Native Object" 这一大段函数都在找那个this指针。@H_419_376@注意,这里面有一个Cocos2d-x引擎经常出现的错误提示InvalID Native Object。底层C++对象被回收了,所以找不到了。

8 (argc == 1) { JsBool arg0; "Js_cocos2dx_Node_setVisible : Error processing arguments" ); cobj->setVisible(arg0); Js_TRUE; CCNode::setVisible(xx)只有一个参数,所以先判断Js的参数个数为1。Js_ValuetoBoolean完成Js对象到C++对象的转换,注意!这是基本类型的转换,和查找对应的对象指针不同。你在gxx-generator生成的代码中会看到大量的这种转换。每次转换都要进行结果判断,如果失败,就打印错误信息。后面是直接调用对应C++对象的setVisible,以及设置返回值。

很繁琐不是吗?如果这种代码全部手写是不是会死人呢。肯定的吧。所以这些代码都是用脚本生成器做出来的(绝大部分)。

后面我们会继续讲解各种Js的绑定代码。

来自:http://blog.csdn.net/kaitiren/article/details/22163193

总结

以上是内存溢出为你收集整理的【cocos2d-x从c++到js】JS与C++的交互1——JS代码调用C++代码全部内容,希望文章能够帮你解决【cocos2d-x从c++到js】JS与C++的交互1——JS代码调用C++代码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1081328.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)