最近在学习cocos2dx和Lua的交互,这里笔记下学习心得。
CONTENTS
备注:
1 作者对于Lua的使用较少,纯粹从使用出发,对它的理解较浅,可能有错误,还请路过的各位大牛多多指正。
2 本笔记代码部分参考cocos2dx2.2.3代码,代码版权归原作者所有。
3 由于作者时间,经验,能力有限,笔记可能不完整,以后随用随补充吧。
HelloLua工程代码分析:
打开HelloLua的代码,发现C代码其实很少,主要的业务逻辑全部在lua脚本中,C代码中只有加载lua脚本的代码,如下:
AppDelegate::~AppDelegate() { 。。。。。。 CCScriptEngineManager::purgeSharedManager(); } bool AppDelegate::applicationDidFinishLaunching() { 。。。。。。 。。。。。。 // register lua engine CCLuaEngine* pEngine = CCLuaEngine::defaultEngine(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename("hello.lua"); pEngine->executeScriptFile(path.c_str()); return true; }
先分析最简单的类:
CCScriptEngineManager:
CCScriptEngineManager是一个单例类,主要用来管理ScriptEngine的指针,代码很简单。个人认为对于这里需要管理的原因是:ScriptEngine是被new出来的,需要一个地方去delete,由于ScriptEngine自己无法找到时机去delete自己,因此需要外部来帮助它delete,因此在游戏退出时,AppDelegate在析构函数中会释放掉ScriptEngine。
所在文件:
CCScriptSupport.h/cpp:
/** CCScriptEngineManager is a singleton which holds an object instance of CCScriptEngineProtocl It helps cocos2d-x and the user code to find back LuaEngine object @since v0.99.5-x-0.8.5 @js NA @lua NA */ class CC_DLL CCScriptEngineManager { public: ~CCScriptEngineManager(void); CCScriptEngineProtocol* getScriptEngine(void) { return m_pScriptEngine;//返回当前管理的ScriptEngine } void setScriptEngine(CCScriptEngineProtocol *pScriptEngine); void removeScriptEngine(void); static CCScriptEngineManager* sharedManager(void); static void purgeSharedManager(void); private: CCScriptEngineManager(void) : m_pScriptEngine(NULL) { } CCScriptEngineProtocol *m_pScriptEngine; }; //=================================== //单例类的唯一实例,默认为NULL static CCScriptEngineManager* s_pSharedScriptEngineManager = NULL; //当单例类被析构时,释放掉本地存储的ScriptEngine。 CCScriptEngineManager::~CCScriptEngineManager(void) { removeScriptEngine(); } //更新本地维护的ScriptEngine的指针。 void CCScriptEngineManager::setScriptEngine(CCScriptEngineProtocol *pScriptEngine) { removeScriptEngine();//先释放本地存储的指针 m_pScriptEngine = pScriptEngine;//然后将新的指针存储下来。 } //删除本地存储的指针。 //个人认为这里的delete可以封装到CCScriptEngineProtocol中抽成一个方法,CCScriptEngineManager简单调用即可,无需把实现细节都放到CCScriptEngineManager中。个人见解,呵呵~~ void CCScriptEngineManager::removeScriptEngine(void) { if (m_pScriptEngine) {//如果本地存储了指针,就把它的内存删掉。 delete m_pScriptEngine; m_pScriptEngine = NULL; } } CCScriptEngineManager* CCScriptEngineManager::sharedManager(void) { if (!s_pSharedScriptEngineManager) {//初始化单例 s_pSharedScriptEngineManager = new CCScriptEngineManager(); } return s_pSharedScriptEngineManager; } //释放单例。 void CCScriptEngineManager::purgeSharedManager(void) { if (s_pSharedScriptEngineManager) { delete s_pSharedScriptEngineManager; s_pSharedScriptEngineManager = NULL; } }
然后看下CCLuaEngine:
CCLuaEngine.h/cpp:
CCLuaEngine如其名称,是Lua脚本的引擎,也是单例。其内部没有太多的Lua交互细节,只是封装了部分函数,主要的内部交互全部在CCLuaStack中完成。
class CCLuaEngine : public CCScriptEngineProtocol { public: static CCLuaEngine* defaultEngine(void); virtual ~CCLuaEngine(void); virtual ccScriptType getScriptType() { return kScriptTypeLua;//返回当前Script的类型 } 。。。。。。 。。。。。。 private: CCLuaEngine(void) : m_stack(NULL)//构造函数时, m_stack置为NNULL { } bool init(void); static CCLuaEngine* m_defaultEngine; //单例类的唯一实例。 CCLuaStack *m_stack;//核心变量,整个CCLuaEngine其实就是对该变量方法的二次封装。 }; //=========================================== //CCLuaEngine的单例实现 CCLuaEngine* CCLuaEngine::m_defaultEngine = NULL; CCLuaEngine* CCLuaEngine::defaultEngine(void) { if (!m_defaultEngine) {//new一个实例来初始化单例,注意这里没有实现单例的销毁,因为单例的销毁放到了 CCScriptEngineManager::removeScriptEngine中了。 m_defaultEngine = new CCLuaEngine(); m_defaultEngine->init(); } return m_defaultEngine; } CCLuaEngine::~CCLuaEngine(void) { //CCLuaEngine被析构时,释放掉m_stack CC_SAFE_RELEASE(m_stack); m_defaultEngine = NULL; } bool CCLuaEngine::init(void) { //CCLuaEngine初始化时,创建一个CCLuaStack,并且retain,防止被析构。 m_stack = CCLuaStack::create(); m_stack->retain(); return true; } //后面的函数全部是对m_stack的封装,笔记到CCLuaStack时详细笔记,这里先略过了。 。。。。。。 。。。。。。
发表评论