您的位置:首页 > 移动开发 > Cocos引擎

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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cocos2dx c++ js bind