好记性不如铅笔头

C && C++, cocos2dx, 编程

cocos2dx-Lua学习笔记:CCScriptEngineManager && CCLuaEngine

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

 

发表评论

3 × 4 =

此站点使用 Akismet 来减少垃圾评论。了解我们如何处理您的评论数据