最近在学习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时详细笔记,这里先略过了。
。。。。。。
。。。。。。
发表评论