cocos2dx-js 绑定c++
2016-07-21 17:24
537 查看
最近在倒腾c++绑定方法到js,供js调用。在此记录一下,供交流和学习。coscos2dx有很多版本,例如cocos2dx-js, -lua版本。使用脚本语言进行协同开发,好处之一就提现在版本升级方面。当修改了逻辑之后,只需要替换本地的响应脚本代码即可。省去了一下审核流程。这里说说c++绑定到js,供js调用c++方法。 主要用到的几个宏:用于声明的宏:
<p class="p1"><span class="s1">#define JS_BINDED_CLASS_GLUE(klass) \</span></p><p class="p1"><span class="s1">static JSClass js_class; \</span></p><p class="p1"><span class="s1">static JSObject* js_proto; \</span></p><p class="p1"><span class="s1">static JSObject* js_parent; \</span></p><p class="p1"><span class="s1">static void _js_register(JSContext* cx, JS::HandleObject global);</span></p>JS_BINDED_CLASS_GLUE,这个宏主要定义了3个变量和1个方法。js_class初始化比较固定:
JSClass jsclass = { "方法名", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
<span style="white-space:pre"> </span> JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,basic_object_finalize };其中basic_object_finalize,一般为该类的销毁方法。功能类似析构函数。js_proto初始化需要调用方法:JS_InitClass
JavaScriptObjCBridge::js_proto = JS_InitClass(cx, global, JS::NullPtr(), &JavaScriptObjCBridge::js_class , JavaScriptObjCBridge::_
<span style="white-space:pre"> </span>js_constructor, 0, props, funcs, NULL, NULL);js_parent初始化直接设置为NULL就行。方法:void_js_register(JSContext*cx, JS::HandleObjectglobal)该方法供js引擎调用,这里面主要的工作就初始化函数调用列表。
<span style="font-family: Arial, Helvetica, sans-serif;">#define JS_BINDED_CONSTRUCTOR(klass) \</span>
static bool _js_constructor(JSContext *cx, unsigned argc, jsval *vp)该方法主要用来对需要注册到js的类进行初始化。初始化的工作内容包括,js_proto,js_parent这个两个变量的初始化,并把加入js引擎里面去。供js调用。
#define JS_BINDED_FUNC(klass, name) \ bool name(JSContext *cx, unsigned argc, jsval *vp)该宏主要定义需要绑定到js的方法名。有一个对应的实现方法:
#define JS_BINDED_FUNC_IMPL(klass, name) \ static bool klass##_func_##name(JSContext *cx, unsigned argc, jsval *vp) { \ JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \ JS::RootedObject thisObj(cx, args.thisv().toObjectOrNull()); \ klass* obj = (klass*)JS_GetPrivate(thisObj); \ if (obj) { \ return obj->name(cx, argc, vp); \ } \ JS_ReportError(cx, "Invalid object call for function %s", #name); \ return false; \ } \ bool klass::name(JSContext *cx, unsigned argc, jsval *vp)判断传过来的参数是否为空,如果不为空,调用name这个方法。此处获取参数的方式与以往版本有所不同。之前获取参数的方式:JS_ARGV这个宏,实际就是把vp这个指针偏移2.现在获取参数的方式:通过方法:JS::CallArgsFromvp(argc,vp).下面以一个简单的例子,删除无关代码。.h
class JavaScriptObjCBridge{ public: JS_BINDED_CLASS_GLUE(JSObjCBridge); JS_BINDED_CONSTRUCTOR(JSObjCBridge); JS_BINDED_FUNC(JSObjCBridge, callStaticMethod); };.cpp
/** * @brief Initialize Object and needed properties. * */ JS_BINDED_CLASS_GLUE_IMPL(JavaScriptObjCBridge); /** * @brief Implementation for the Javascript Constructor * */ JS_BINDED_CONSTRUCTOR_IMPL(JavaScriptObjCBridge) { JavaScriptObjCBridge* jsj = new (std::nothrow) JavaScriptObjCBridge(); js_proxy_t *p; jsval out; JS::RootedObject proto(cx, JavaScriptObjCBridge::js_proto); JS::RootedObject parentProto(cx, JavaScriptObjCBridge::js_parent); JS::RootedObject obj(cx, JS_NewObject(cx, &JavaScriptObjCBridge::js_class, proto, parentProto)); if (obj) { JS_SetPrivate(obj, jsj); out = OBJECT_TO_JSVAL(obj); } JS::CallArgs args = JS::CallArgsFromVp(argc, vp); args.rval().set(out); p = jsb_new_proxy(jsj, obj); JS::AddNamedObjectRoot(cx, &p->obj, "JavaScriptObjCBridge"); return true; } /** * @brief destructor for Javascript * */ static void basic_object_finalize(JSFreeOp *freeOp, JSObject *obj) { CCLOG("basic_object_finalize %p ...", obj); js_proxy_t* nproxy; js_proxy_t* jsproxy; JSContext *cx = ScriptingCore::getInstance()->getGlobalContext(); JS::RootedObject jsobj(cx, obj); jsproxy = jsb_get_js_proxy(jsobj); if (jsproxy) { nproxy = jsb_get_native_proxy(jsproxy->ptr); jsb_remove_proxy(nproxy, jsproxy); } }
<p class="p1"><span class="s1">JS_BINDED_FUNC_IMPL</span><span class="s2">(</span><span class="s3">JavaScriptObjCBridge</span><span class="s2">, callStaticMethod){</span></p><p class="p1"><span class="s2"> </span><span class="s3">JS</span><span class="s2">::</span><span class="s3">CallArgs</span><span class="s2"> args = </span><span class="s3">JS</span><span class="s2">::</span><span class="s3">CallArgsFromVp</span><span class="s2">(argc, vp);</span></p><p class="p1"><span class="s2"> </span><span class="s1">if</span><span class="s2"> (argc >= 2) {</span></p><p class="p1"><span class="s2"> </span><span class="s3">JSStringWrapper</span><span class="s2"> arg0(args.</span><span class="s3">get</span><span class="s2">(0));</span></p><p class="p1"><span class="s2"> </span><span class="s3">JSStringWrapper</span><span class="s2"> arg1(args.</span><span class="s3">get</span><span class="s2">(1));</span></p><p class="p1"><span class="s2"> </span><span class="s3">CallInfo</span><span class="s2"> call(arg0.</span><span class="s3">get</span><span class="s2">(),arg1.</span><span class="s3">get</span><span class="s2">());</span></p><p class="p1"><span class="s2"> </span><span class="s1">bool</span><span class="s2"> ok = call.</span><span class="s3">execute</span><span class="s2">(cx,args.</span><span class="s3">array</span><span class="s2">(),argc);</span></p><p class="p1"><span class="s2"> </span><span class="s1">if</span><span class="s2">(!ok){</span></p><p class="p2"><span class="s4"> </span><span class="s3">JS_ReportError</span><span class="s4">(cx, </span><span class="s2">"js_cocos2dx_JSObjCBridge : call result code: %d"</s d6b9 pan><span class="s4">, call.</span><span class="s3">getErrorCode</span><span class="s4">());</span></p><p class="p1"><span class="s2"> </span><span class="s1">return</span><span class="s2"> </span><span class="s1">false</span><span class="s2">;</span></p><p class="p1"><span class="s2"> }</span></p><p class="p3"><span class="s4"> args.</span><span class="s2">rval</span><span class="s4">().</span><span class="s2">set</span><span class="s4">(</span><span class="s2">convertReturnValue</span><span class="s4">(cx, call.</span><span class="s2">getReturnValue</span><span class="s4">(), call.</span><span class="s2">getReturnValueType</span><span class="s4">()));</span></p><p class="p1"><span class="s2"> </span><span class="s1">return</span><span class="s2"> ok;</span></p><p class="p1"><span class="s2"> }</span></p><p class="p4"><span class="s4"> </span><span class="s2">return</span><span class="s4"> </span><span class="s2">false</span><span class="s4">;</span></p><p class="p1"><span class="s2">}</span></p>
<p class="p1"><span class="s1">/**</span></p><p class="p1"><span class="s1"> * @brief register JavascriptJavaBridge to be usable in js</span></p><p class="p1"><span class="s1"> *</span></p><p class="p1"><span class="s1"> */</span></p><p class="p2"><span class="s2">void</span><span class="s3"> </span><span class="s1">JavaScriptObjCBridge</span><span class="s3">::_js_register(</span><span class="s1">JSContext</span><span class="s3"> *cx, </span><span class="s1">JS</span><span class="s3">::</span><span class="s1">HandleObject</span><span class="s3"> global)</span></p><p class="p3"><span class="s1">{</span></p><p class="p3"><span class="s1"> </span><span class="s4">JSClass</span><span class="s1"> jsclass = {</span></p><p class="p2"><span class="s3"> </span><span class="s5">"JavaScriptObjCBridge"</span><span class="s3">, </span><span class="s2">JSCLASS_HAS_PRIVATE</span><span class="s3">, </span><span class="s1">JS_PropertyStub</span><span class="s3">, </span><span class="s1">JS_DeletePropertyStub</span><span class="s3">, </span><span class="s1">JS_PropertyStub</span><span class="s3">, </span><span class="s1">JS_StrictPropertyStub</span><span class="s3">, </span><span class="s1">JS_EnumerateStub</span><span class="s3">, </span><span class="s1">JS_ResolveStub</span><span class="s3">, </span><span class="s1">JS_ConvertStub</span><span class="s3">,</span><span class="s1">basic_object_finalize</span></p><p class="p3"><span class="s1"> };</span></p><p class="p4"><span class="s1"> </span></p><p class="p2"><span class="s3"> </span><span class="s1">JavaScriptObjCBridge</span><span class="s3">::</span><span class="s1">js_class</span><span class="s3"> = jsclass;</span></p><p class="p3"><span class="s1"> </span><span class="s2">static</span><span class="s1"> </span><span class="s4">JSPropertySpec</span><span class="s1"> props[] = {</span></p><p class="p5"><span class="s3"> </span><span class="s1">JS_PSG</span><span class="s3">(</span><span class="s5">"__nativeObj"</span><span class="s3">, </span><span class="s4">js_is_native_obj</span><span class="s3">, </span><span class="s1">JSPROP_PERMANENT</span><span class="s3"> | </span><span class="s1">JSPROP_ENUMERATE</span><span class="s3"> ),</span></p><p class="p5"><span class="s3"> </span><span class="s1">JS_PS_END</span></p><p class="p3"><span class="s1"> };</span></p><p class="p4"><span class="s1"> </span></p><p class="p3"><span class="s1"> </span><span class="s2">static</span><span class="s1"> </span><span class="s4">JSFunctionSpec</span><span class="s1"> funcs[] = {</span></p><p class="p3"><span class="s1"> </span><span class="s2">JS_BINDED_FUNC_FOR_DEF</span><span class="s1">(JavaScriptObjCBridge, callStaticMethod),</span></p><p class="p5"><span class="s3"> </span><span class="s1">JS_FS_END</span></p><p class="p3"><span class="s1"> };</span></p><p class="p4"><span class="s1"> </span></p><p class="p2"><span class="s3"> </span><span class="s1">JavaScriptObjCBridge</span><span class="s3">::</span><span class="s1">js_parent</span><span class="s3"> = </span><span class="s2">NULL</span><span class="s3">;</span></p><p class="p2"><span class="s3"> </span><span class="s1">JavaScriptObjCBridge</span><span class="s3">::</span><span class="s1">js_proto</span><span class="s3"> = </span><span class="s1">JS_InitClass</span><span class="s3">(cx, global, </span><span class="s1">JS</span><span class="s3">::</span><span class="s1">NullPtr</span><span class="s3">(), &</span><span class="s1">JavaScriptObjCBridge</span><span class="s3">::</span><span class="s1">js_class</span><span class="s3"> , </span><span class="s1">JavaScriptObjCBridge</span><span class="s3">::</span><span class="s1">_js_constructor</span><span class="s3">, 0, props, funcs, </span><span class="s2">NULL</span><span class="s3">, </span><span class="s2">NULL</span><span class="s3">);</span></p><p class="p3"><span class="s1">}</span></p><p class="p4"><span class="s1"></span></p>
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Extjs4.0 最新最全视频教程
- 如何使用 bind 设置 DNS 服务器
- Javascript中toFixed方法的改进
- 关于指针的一些事情
- 5个常见可用性错误和解决方案
- js数组实现图片轮播
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- js可突破windows弹退效果代码
- JSP脚本漏洞面面观
- 使用BAT一句话命令实现快速合并JS、CSS
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- js显示当前星期的起止日期的脚本
- Lua教程(二):C++和Lua相互传递数据示例
- Jquery绑定事件(bind和live的区别介绍)
- 爆炸式的JS圆形浮动菜单特效代码
- C++联合体转换成C#结构的实现方法
- js select常用操作控制代码