cocos2dx 3.x bindings-generator(Part one)
一、bindings-generator 当有一些感觉狂拽炫酷屌的 C or C++ 函数库想加到专案里时,难免会用上 cocos2d-x 自带的 bindings-generator 产出库让 lua 调用。 在 3.0 rc0 以前的说明并不像稳定版本这么“比较”多一些,花在 trial and error 上的时间也就相对的多了许多。过去的就说好不提了,单从现在稳定版的简单描述流程:
注意事项:
嗯,拿 cocos2d-x 自己的玩意来当例子: 在 EventDispatcher 类中有一个函数是这么被定义的: EventListenerCustom* addCustomEventListener(const std::string &eventName,const std::function # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.
script_control_cpp = yes
在要挂载的函数库里有控制对象的生成与销毁的话麻烦这选项请填no,尤其是有写什么管理者来管理对象的更是要留意。
cocos2d-x 3.0rc0 - bindings-generator 问题与解决 这是先前针对 3.0 rc0 时所写的一点小吐槽,里头有简单的相关设定,烦请参考。 二、挂载自定义函式库 本来呢,以为将产生好的头文件与源码放到想摆放的位置,再参考lua-tests 里如何挂载自定义函式库到 lua 就成了,但是…… 天底下哪有这么便宜的事! 先看一下lua-tests 的 AppDelegate.cpp 中的相关内容: // register lua engine
LuaEngine* pEngine = LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(pEngine);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID ||CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
LuaStack* stack = pEngine->getLuaStack();
register_assetsmanager_test_sample(stack->getLuaState());
#endif
很单蠢,喔不,是看起来再单纯不过了咩。只要把那个 register_assetsmanager_test_sample( ) 替换成自订库产生出来的register_all_ooxx_bindings( ) 不就行了? 可以试试,不过应该是程序崩溃才是。原因?让我们看下去…… 嗯,底下问题解说的会有些生硬,如果只想看解决方法的话可直接跳过,毕竟不影响大局嘛。 问题: LuaEngine 被初始时会建立起 LuaStack 对象,而真正 lua 栈对象 luaStack 的建立、挂载 cocos2d-x 自己的 modules、读入一些外部库(如 luasock、lsqlite)这些行为都是在 LuaStack 被建立起时一并完成的。 流程大概是这样: LuaEngine::getInstance() → new LuaEngine → LuaEngine::init() → LuaStack::create() → LuaStack::init() 可以打开 CCLuaStack.cpp 瞧一下,位置约莫在 cocos/scripting/lua-bindings/manual/ 底下,看一下 LuaStack::init() 函数,就会明白上头再说些什么东西来着。 话说回来,这怎么会造成挂载自己库时程序崩溃呢? 为了处理 2.x <-> 3.0 之间转换的问题,在LuaEngine::init() 时执行了三个 .lua: bool LuaEngine::init(void) { _stack = LuaStack::create(); _stack->retain(); executeScriptFile("DeprecatedEnum.lua"); executeScriptFile("DeprecatedClass.lua"); executeScriptFile("Deprecated.lua"); return true; } 问题就出在执行 executeScriptFile() 后,为了让 lua 的栈能够被正常的再使用,执行完后都会将 lua 栈归零。 int LuaEngine::executeScriptFile(const char* filename) { int ret = _stack->executeScriptFile(filename); _stack->clean(); // 这里会归零,就是很简单的调用 lua_settop(_state,0) return ret; } 归零并不是错误的!问题点是在处理完后要挂载自己输出库的时间点,摆个简单转换后要挂载的函数的内容看一下: TOLUA_API int register_all_ooxx_bindings(lua_State* tolua_S) { tolua_open(tolua_S); tolua_module(tolua_S,"ooxx",0); tolua_beginmodule(tolua_S,"ooxx"); lua_register_ooxx_bindings_TalkComponent(tolua_S); tolua_endmodule(tolua_S); return 1; } 如果什么事都不处理,按照前文提到的仿照lua-test 的AppDelegate.cpp 一样把自己的库挂上去: // register lua engine LuaEngine* pEngine = LuaEngine::getInstance(); ScriptEngineManager::getInstance()->setScriptEngine(pEngine); LuaStack* stack = pEngine->getLuaStack(); register_all_ooxx_bindings(stack->getLuaState()); 执行之……就会发现死在tolua_module( ) !一般而言,应该都是死在tolua_module( ) 里的 lua_rawget(L,-2): TOLUA_API void tolua_module (lua_State* L,const char* name,int hasvar) { if (name) { /* tolua module */ lua_pushstring(L,name); lua_rawget(L,-2); // <- 会死在这里! if (!lua_istable(L,-1)) /* check if module already exists */ 为什么? 熟悉 lua c API 的看后应该就知道问题点。 想去取得 -2 index 的栈值,但此时栈内仅有一个字串,其他完全是空的,不死才是不科学! 整个整理一下,会挂掉的原因出于执行了三个标记已过时便于转换用的 .lua chunk file,然后 lua 栈被归零,最后要挂载自订库,然后……就没有再然后了…… 解决: 有两个方法可以解决。 一个是先前随便乱回答的偷机方法:打开 LuaEngine.cpp,把那三行执行 .lua 的注解掉,最后把执行那三个 .lua 的移到挂载完自己的函数库后再执行就成了。 传送门,请按 详细可看上头连结,虽然写得有些啰唆…… 第二个法子单纯点,既然栈是空的那就给他资料不就得了: auto engine = LuaEngine::getInstance(); ScriptEngineManager::getInstance()->setScriptEngine(engine); auto luaStack = engine->getLuaStack()->getLuaState(); if (luaStack) { lua_getglobal(luaStack,"_G"); register_all_ooxx_bindings(luaStack); lua_settop(luaStack,0); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |