此文章接:点击查看绑定C++给JS调用 这篇文章而来.
Cocos2d-x JS项目中JS调用C++,相对比较简单,在前一篇文章也做了说明。主要是绑定C++给JS调用。相对简单,那昨天看到论坛里好多朋友一直在讨论C++调用JS的问题,好象都有一些奇怪的问题,今天做了一个测试DEMO。下面分几点来看一下。
改造之前的C++类(Eraylayer)
新增一个Delegate类,为ErayLayer添加设置Delegate类,ErayLayer头文件如下:
class ErayDelegate:public cocos2d::Ref { public: virtual void onClick(const std::string& value) {}; virtual ~ErayDelegate() {}; }; class ErayLayer :public cocos2d::Layer { public: ErayLayer(); ~ErayLayer(); virtual bool init(); CREATE_FUNC(ErayLayer); void setDelegate(ErayDelegate* _delegate); private: ErayDelegate* m_pDelegate; };
CPP文件如下:
ErayLayer::ErayLayer() { m_pDelegate = nullptr; } ErayLayer::~ErayLayer() { CC_SAFE_RELEASE(m_pDelegate); } bool ErayLayer::init() { if (!Layer::init()) { return false; } ImageView* image = ImageView::create(); image->loadTexture("res/diamond3.png"); image->setTouchEnabled(true); image->addTouchEventListener([=](Ref *pSender, ui::Widget::TouchEventType type) { if (type != ui::Widget::TouchEventType::ENDED) return; if (m_pDelegate) { m_pDelegate->onClick("call from cpp"); } CCLOG("click on Image"); }); image->setPosition(Vec2(300.0f, 300.0f)); addChild(image); return true; } /** * @brief 设置代理执行类 */ void ErayLayer::setDelegate(ErayDelegate* _delegate) { if (_delegate) { m_pDelegate = _delegate; m_pDelegate->retain(); } }
新增jsb_coolexp_manual.hpp,jsb_coolexp_manual.cpp,主要代码如下:
〈pre>
class JSB_ErayDelegate :public ErayDelegate {
public:
JSB_ErayDelegate() {
}
virtual void onClick(const std::string& value) override {
// 执行代理的方法
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
jsval arg = std_string_to_jsval(cx, value);
JS::RootedValue delegateVal(cx, _JSDelegate);
ScriptingCore::getInstance()->executeFunctionWithOwner(delegateVal, "onClick", 1, &arg);
// 调用一个全部的对象的方法
JSContext * context = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedObject object(context, ScriptingCore::getInstance()->getGlobalObject());
JS::RootedValue owner(context);
jsval arg1 = INT_TO_JSVAL(1001);
JS_GetProperty(context, object, "Config", &owner);
ScriptingCore::getInstance()->executeFunctionWithOwner(owner, "sendNumber", 1, &arg1);
}
void setJSDelegate(JS::HandleValue pJSDelegate)
{
_JSDelegate = pJSDelegate;
}
private:
JS::Heap
};
static bool jsb_ErayLayer_setJSHandler(JSContext cx, uint32_t argc, jsval vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t proxy = jsb_get_js_proxy(obj);
ErayLayer cobj = (ErayLayer )(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2(cobj, cx, false, “Invalid Native Object”);
if (argc == 1)
{
// save the delegate
JSB_ErayDelegate nativeDelegate = new (std::nothrow) JSB_ErayDelegate();
nativeDelegate->setJSDelegate(args.get(0));
cobj->setDelegate(nativeDelegate);
args.rval().setUndefined();
nativeDelegate->release();
return true;
}
JS_ReportError(cx, “wrong number of arguments: %d, was expecting %d”, argc, 1);
return false;
}
extern JSObject jsb_ErayLayer_prototype;
void register_all_coolexp_manual(JSContext cx, JS::HandleObject global)
{
JS::RootedObject proto(cx, jsb_ErayLayer_prototype);
JS_DefineFunction(cx, proto, “setJSDelegate”, jsb_ErayLayer_setJSHandler, 1, JSPROP_ENUMERATE | JSPROP_PERMANENT);
}
JS文件内容:
var erayLayer = ErayLayer.create(); this.addChild(erayLayer); erayLayer.setJSDelegate({ "onClick":function(value){ cc.log("onClick:%s",value); } }); // 写在JS顶层 var Config = Config || {}; Config.sendNumber = function(num) { cc.log("From javascript: " + num); };
运行点击场景上的图片,看打印输出
参考文件:点击查看