Cocos2d-x的SprideMonkey的JavaScript与C++的交互

来源:互联网 发布:mac地址冲突的后果 编辑:程序博客网 时间:2024/05/19 05:01

本文转载自:http://blog.csdn.net/spiritring/article/details/8969128

(一)

1.如果想在c++里面注册一个JS函数..需要使用JS_DefineFunction.这个函数是 蜘蛛猴的函数..咱们可以直接使用的.比如我想闹个叫TS_Out的函数.然后有n个参数.那么就可以这样写.

[cpp] view plaincopy
  1. void TSScriptJS::Init()  
  2. {  
  3.     ScriptingCore* sc = ScriptingCore::getInstance();  
  4.     JSFunction* pF = JS_DefineFunction(sc->getGlobalContext(), sc->getGlobalObject(), "TS_JSOut",  
  5.         TSScriptJS::TS_JSOut, 0, JSPROP_READONLY | JSPROP_PERMANENT);  
  6. }  

下面是回调:
[cpp] view plaincopy
  1. JSBool TSScriptJS::TS_JSOut( JSContext *cx, uint32_t argc, jsval *vp )  
  2. {  
  3.     if (argc > 0) {  
  4.         JSString *string = NULL;  
  5.         JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &string);  
  6.         if (string) {  
  7.             JSStringWrapper wrapper(string);  
  8.             //这块就有值了  
  9.         }  
  10.     }  
  11.     return JS_TRUE;  
  12. }  

然后JS里面就可以这样调用了.

[javascript] view plaincopy
  1. TS_JSOut("Timeshift This is Awesome Engine!");  
呵呵原谅我的自恋.....偷笑

2.c++可以主动调用这个函数并传入参数.这个功能非常重要.因为c++为主要的开发中,主要是需要js的这种交互操作的.就是说..c++需要js里面的值

[cpp] view plaincopy
  1. jsval TSScriptJS::JSCallFuncName(const char *name, int count, ...)  
  2. {  
  3.     ScriptingCore* sc = ScriptingCore::getInstance();  
  4.     int argc = count;  
  5.     jsval res;  
  6.     jsval *argv = new jsval[count];  
  7.     va_list insvalist;  
  8.     va_start(insvalist,count);  
  9.     for (int i = 0; i < count; ++i)  
  10.     {  
  11.         argv[i] = std_string_to_jsval(sc->getGlobalContext(),std::string(va_arg(insvalist,const char *)));  
  12.     }  
  13.     va_end(insvalist) ;  
  14.     JS_CallFunctionName(sc->getGlobalContext(), sc->getGlobalObject(), name, argc, argv, &res);  
  15.     delete [] argv;  
  16.     return res ;  
  17. }  
这个帅的掉渣的函数意思就是说..哦 name就是函数名字了. count就是有几个参数.然后后面我为了方便都传入的字符串..您可以随心而乐的.如果不怕麻烦..呵呵.

然后会返回一个 jsval.这个是个非常强大结构..他可以是任何类型的东西.spidermonke给了很多函数.cocos2d-x也给了很多来转化这个类型到熟知的c++类型.

[cpp] view plaincopy
  1. jsval pR = TSScriptJS::GetSingleTon()->JSCallFuncName("TS_JSMain",3,"haha!","hoho!","heihei!");  
  2. JSString* pS = JS_ValueToString(ScriptingCore::getInstance()->getGlobalContext(), pR);  
  3. JSStringWrapper pW(pS);  
  4. CCLog(pW.get().c_str());  
好了现在定义这个叫做 TS_JSMain的函数在JS中吧.

[javascript] view plaincopy
  1. function TS_JSMain(v1,v2,v3) {  
  2.     try  
  3.     {  
  4.         cc.log(v1+v2+v3);  
  5.     }  
  6.     catch(e)  
  7.     {  
  8.         cc.log("出事了!!" + e);  
  9.         return;  
  10.     }  
  11.   
  12.     return "TimeShift is Awesome!";  
  13. }  

好了变量什么的读取和写值.请见下一节..!

(二)

首先来理解一下sc->getGlobalObject()...这个同学们就问了..你这个不科学...sc是个毛线呀...这块璞哥就说了.不能怪我呀.这要下班了.伤不起呀....璞哥一直说要随心而乐.嘛.是吧.一个礼拜就盼这个呢....好了不扯了.sc就是cocos2d-x给咱封装的那个单键..用过的同学.和看过源码的同学肯定知道cocos2d-x有很多的单键..什么导演呀.xxx是吧..ScriptingCore* sc = ScriptingCore::getInstance(); 关于整个cocos2d-x的js核心类就是这个东东.ScriptingCore.通过这个可以获取到 Root JSObject和 JS上下文.这两个非常重要的东西.下面的实例就是说.在根节点下面取到 x这个变量.后面的东西也就非常好理解了.

一.JS全局变量的操作.

1.修改值.

该例子是说.js里面有个全局变量x.现在把x获取到c++中. 这块是个字符串.

[cpp] view plaincopy
  1. jsval x;  
  2. JS_GetProperty(sc->getGlobalContext(), sc->getGlobalObject(), "x", &x);  
  3. JSString* pS = JS_ValueToString(ScriptingCore::getInstance()->getGlobalContext(), x);  
  4. JSStringWrapper pW(pS);  
  5. CCLog(pW.get().c_str());  

2.获取值.

改例子是说.js里面有个全局变量x.现在通过c++把值给设置成HelloWorld!

[cpp] view plaincopy
  1. jsval x = c_string_to_jsval(sc->getGlobalContext(), "HelloWorld!");  
  2. JS_SetProperty(sc->getGlobalContext(), sc->getGlobalObject(), "x", &x);  

待续...复杂的Arry和Object.

(三)

全局变量Obj的操作.

这个是作为JS脚本来说非常有用处的一个地方.比如说.咱们想在JS脚本中存下窗口位置和大小.还有其他杂七杂八的东西.对游戏或者应用开发来说是在平常不过的需求了.本人也是想说..lua这个东东吧..越来越淡薄了..哎~ TS3选择lua真是个惨痛的代价..抓狂..还写了个IDE来调试他 哎~.看来我真是浪费功夫.浪费的太多了.这一节.璞哥给大家闹这个obj...大家别说这篇 篇幅小哦...是在没辙.就是很简单...懂JS的同学肯定都知道 js是个非常非常弱类型的语言..所有的东东都能Obj...啥都能Obj里面塞..不知道的同学可以看看本人blog里面关于Javascript数据结构的文章..估计就会豁然开朗了吧.呵呵.

JavaScript脚本里面可以这样写..然后咱们要去读取MM的值..这块就读下字符串..其他类型当然也可以读到了.如果有什么不明白的地方欢迎加我Q群.就在blog帖子置顶贴上面.

[javascript] view plaincopy
  1. var obj = {};  
  2. obj.MM = "TimeShift Engine Awesome!"  

然后cpp里面就可以这样读出MM的值..

[cpp] view plaincopy
  1. ScriptingCore* sc = ScriptingCore::getInstance();  
  2. sc->runScript("CMAI/main.js");  
  3. {  
  4.     JSObject* pObj = nullptr;  
  5.     jsval obj;  
  6.     JS_GetProperty(sc->getGlobalContext(),sc->getGlobalObject(),"obj", &obj);  
  7.     JS_ValueToObject(sc->getGlobalContext(),obj,&pObj);  
  8.   
  9.     jsval mm;  
  10.     JS_GetProperty(sc->getGlobalContext(),pObj,"MM", &mm);  
  11.     JSString* pS = JS_ValueToString(sc->getGlobalContext(), mm);  
  12.     JSStringWrapper pW(pS);  
  13.     CCLog(pW.get().c_str());  
  14. }  

实际上代码很简单.就是说. 全局root的JSObject里面有个obj变量..然后获取obj变量之后呢.发现jsval里面是个JSObject..然后这个JSObject肯定里面就有MM了哦...然后就..各位同学你懂的..然后就转化出来字符串了

(四)

cocos2d-x里面有个封装叫evalString.意思就是说运行一句JS.. 好吧.你们懂了哦.~~~虽然方式比较猥琐.但是不乏是个好方法..比如配合JSON是吧...

[cpp] view plaincopy
  1. bool TSScriptJS::RunFunction( std::string funName, std::string arg )  
  2. {  
  3.     std::string rStr = funName + "(\"" + arg + "\");";  
  4.     jsval v1;  
  5.     JSBool r = ScriptingCore::getInstance()->evalString(rStr.c_str(), &v1);  
  6.     return r;  
  7. }  
这是本帅.的一个运行函数的封装.虽然取不到返回值.但是..还是可以跑的.对不对.....

本人根据文章写的代码(cocos2d-x 2.2.1版本):http://download.csdn.net/detail/qwezcl/7627365

把代码放在cocos2d-x 2.2.1  => projects目录下即可运行:


0 0
原创粉丝点击