quick cocos2dx-lua引擎怎样找到main.lua函数?

使用quick cocos2d-x Lua的小伙伴都知道:

main.lua:  程序入口
src:       放代码文件
res:       放资源文件

一个有意思的问题是,main.lua是怎样被cocos引擎找到的呢?
为了满足大家的好奇心,一起去探究吧~
引擎版本:quick cocos2dx-Lua community 3.6.1 release
阅读工具:sublime

0.问题描述

登录流程: 从引擎启动到main.lua的流程

1.阅读Source Code

首先,找到引擎程序入口(以win32平台为例, mac, linux, ios, Android类似):
(Quick-Cocos2dx-Community目录)\quick\templates\lua-template-quick\frameworks\runtime-src\proj.win32\main.cpp

int APIENTRY _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow)
{
    ...
    // create the application instance
    AppDelegate app;
    int ret = Application::getInstance()->run();
    ...
    return ret;
}

注意到int ret = Application::getInstance()->run()这一行
Application::getInstance()->run()这个怎么找到的呢
去Application类的定义(sublime选中Application, 右键 -> go to definition)

class CC_DLL Application : public ApplicationProtocol
{
public:
    ...
    /**
    @brief    Run the message loop.
    */
    int run();

    /**
    @brief    Get current applicaiton instance.
    @return Current application instance pointer.
    */
    static Application* getInstance();
    ...
};

原来,Application::getInstance()得到的是一个Application的指针
接着,调用run()函数
在Application.cpp里有run()函数实现如下:

int Application::run()
{
    ...
    // Initialize instance and cocos2d.
    if (!applicationDidFinishLaunching())
    {
        return 0;
    }
    ...
}

接下来,我们进入applicationDidFinishLaunching()函数(就在Application类里面),可以看到


bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();    
    if(!glview) {
        string title = "__PROJECT_COCOS_NAME__";
        glview = cocos2d::GLViewImpl::create(title.c_str());
        director->setOpenGLView(glview);
        director->startAnimation();
    }
   
    auto engine = LuaEngine::getInstance();
    ScriptEngineManager::getInstance()->setScriptEngine(engine);
    lua_State* L = engine->getLuaStack()->getLuaState();
    lua_module_register(L);

    // use Quick-Cocos2d-X
    quick_module_register(L);

    LuaStack* stack = engine->getLuaStack();
#if ANYSDK_DEFINE > 0
    lua_getglobal(stack->getLuaState(), "_G");
    tolua_anysdk_open(stack->getLuaState());
    tolua_anysdk_manual_open(stack->getLuaState());
    lua_pop(stack->getLuaState(), 1);
#endif

    //register custom function
    //LuaStack* stack = engine->getLuaStack();
    //register_custom_function(stack->getLuaState());
    
    //FileUtils::getInstance()->setResourceEncryptKeyAndSign("test", "XXTEA");
#if 0
    // use luajit bytecode package
    stack->setXXTEAKeyAndSign("2dxLua", "XXTEA");
    
#ifdef CC_TARGET_OS_IPHONE
    if (sizeof(long) == 4) {
        stack->loadChunksFromZIP("res/game.zip");
    } else {
        stack->loadChunksFromZIP("res/game64.zip");
    }
#else
    // android, mac, win32, etc
    stack->loadChunksFromZIP("res/game.zip");
#endif
    stack->executeString("require 'main'");
#else // #if 0
    // use discrete files
    engine->executeScriptFile("src/main.lua");
#endif

    return true;
}

代码末尾的那个代码,你瞧见了吗?

engine->executeScriptFile("src/main.lua");

2.事后Feeling

其实找到这里,发现挺easy的哦!
那么,src和res路径是怎么有的呢?
不过瘾~~
好奇的我决定再来一发: 为啥代码放src目录, 资源放res目录?

3.Again阅读Source

当我决定再来一发的时候,
才发现自己把类AppDelegate找错了
类AppDelegate找错了
错了??
那不是之前的得白来??不然,差不多是类似的:
重新梳理一遍
当我们启动quick player界面的时候:点击"示例",然后有"一个塔防演示",点击它,有塔防示例在运行
那么到底做了什么事情呢?
看debug log

...
Quick-Cocos2dx-Community C++ support ready.

------------------------------------------------

LOAD LUA FILE: D:/ProgramFiles/cocos/Quick-Cocos2dx-Community/quick/samples/towerdefense/src/main.lua

------------------------------------------------

[LUA-print] ===========================================================

[LUA-print]               LOAD QUICK FRAMEWORK

[LUA-print] ===========================================================

[LUA-print] [INFO] 
...

聪明机智的我首先全局搜索下面这句话

Quick-Cocos2dx-Community C++ support ready.

sublime里Ctrl+Shift+F,输入"Quick-Cocos2dx-Community C++ support ready."
出来一堆...

Searching 3602 files for "Quick-Cocos2dx-Community C++ support ready."

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\external\lua\quick\lua_cocos2dx_quick_manual.cpp:
  428      extendNode(tolua_S);
  429  
  430:     CCLOG("Quick-Cocos2dx-Community C++ support ready.");
  431      
  432      return 0;

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\player\player3.app\Contents\MacOS\player3:
    <binary>

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\samples\2048\debug.log:
    1: Quick-Cocos2dx-Community C++ support ready.
    2  
    3  ------------------------------------------------

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\samples\armature\debug.log:
    1: Quick-Cocos2dx-Community C++ support ready.
    2  
    3  ------------------------------------------------
...

仔细一看,除了第一个是.cpp, 其它全是.log
机智的我点第一个进去看

int register_all_quick_manual(lua_State* tolua_S)
{
    if (nullptr == tolua_S)
        return 0;
    
    extendFunctions(tolua_S);
    extendNode(tolua_S);

    CCLOG("Quick-Cocos2dx-Community C++ support ready.");
    
    return 0;
}

既然出现了Quick-Cocos2dx-Community C++ support ready.说明包含这句代码的函数(即register_all_quick_manual(lua_State* tolua_S))肯定是被调用的!
机智的我再来一次全局搜索: sublimeCtrl+Shift+F

Searching 3602 files for "register_all_quick_manual"

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\external\lua\quick\lua_cocos2dx_quick_manual.cpp:
  420  }
  421  
  422: int register_all_quick_manual(lua_State* tolua_S)
  423  {
  424      if (nullptr == tolua_S)

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\external\lua\quick\lua_cocos2dx_quick_manual.hpp:
   14  USING_NS_CC;
   15  
   16: TOLUA_API int register_all_quick_manual(lua_State* tolua_S);
   17  
   18  #endif // #ifndef COCOS2DX_SCRIPT_LUA_COCOS2DX_SUPPORT_GENERATED_LUA_COCOS2DX_QUICK_MANUAL_H

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\player\Classes\AppDelegate.cpp:
   28      if (lua_istable(L, -1))//stack:...,_G,
   29      {
   30:         register_all_quick_manual(L);
   31          luaopen_cocos2dx_extra_luabinding(L);
   32          register_all_cocos2dx_extension_filter(L);

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\templates\lua-template-quick\frameworks\runtime-src\Classes\AppDelegate.cpp:
   34      if (lua_istable(L, -1))//stack:...,_G,
   35      {
   36:         register_all_quick_manual(L);
   37          // extra
   38          luaopen_cocos2dx_extra_luabinding(L);

4 matches across 4 files

3个.cpp文件,一个.hpp文件,到底是哪个呢?
.hpp头文件定义,排除;第一个.cpp就是本身定义的文件,不涉及调用,剩下的两个.cpp究竟是哪一个呢?
而且都是AppDelegate.cpp

...\quick\player\Classes\AppDelegate.cpp
...\quick\templates\lua-template-quick\frameworks\runtime-src\Classes\AppDelegate.cpp

然后,再来
debug目录里有这么一个

Quick-Cocos2dx-Community C++ support ready.

------------------------------------------------

LOAD LUA FILE: D:/ProgramFiles/cocos/Quick-Cocos2dx-Community/quick/samples/towerdefense/src/main.lua

------------------------------------------------

全局搜下面这句

LOAD LUA FILE:

搜索结果如下:

Searching 3602 files for "LOAD LUA FILE: "

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\player\Classes\AppDelegate.cpp:
  166      
  167      CCLOG("------------------------------------------------");
  168:     CCLOG("LOAD LUA FILE: %s", path.c_str());
  169      CCLOG("------------------------------------------------");
  170      engine->executeScriptFile(path.c_str());

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\player\player3.app\Contents\MacOS\player3:
    <binary>

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\samples\2048\debug.log:
    3  ------------------------------------------------
    4  
    5: LOAD LUA FILE: D:/cocos2d-x/Quick-Cocos2dx-Community/quick/samples/2048/src/main.lua
    6  
    7  ------------------------------------------------

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\samples\armature\debug.log:
    3  ------------------------------------------------
    4  
    5: LOAD LUA FILE: D:/ProgramFiles/cocos/Quick-Cocos2dx-Community/quick/samples/armature/src/main.lua
    6  
    7  ------------------------------------------------

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\samples\benchmark\debug.log:
   23  Quick-Cocos2dx-Community C++ support ready.

除了第一个是.cpp外,其它都是.log文件...仔细一看

D:\ProgramFiles\cocos\Quick-Cocos2dx-Community\quick\player\Classes\AppDelegate.cpp:

机智如我,确定运行程序时是上面这个AppDelegate.cpp文件了
然后点进去一看

void StartupCall::startup()
{
    ...
    
    // load script
    string env = "__LUA_STARTUP_FILE__=\"";
    env.append(path);
    env.append("\"");
    engine->executeString(env.c_str());
    
    CCLOG("------------------------------------------------");
    CCLOG("LOAD LUA FILE: %s", path.c_str());
    CCLOG("------------------------------------------------");
    engine->executeScriptFile(path.c_str());
    
    // track start event
    trackLaunchEvent();
}

日志末尾有

CCLOG("------------------------------------------------");
CCLOG("LOAD LUA FILE: %s", path.c_str());
CCLOG("------------------------------------------------");
engine->executeScriptFile(path.c_str());

看第三行, 原来engine->executeScriptFile(path.c_str());
而path.c_str()被打印了出来, 就是
D:/ProgramFiles/cocos/Quick-Cocos2dx-Community/quick/samples/towerdefense/src/main.lua
main.lua找到啦!
main.lua找到啦!
main.lua找到啦!

Quick-Cocos2dx-Community C++ support ready.

------------------------------------------------

LOAD LUA FILE: D:/ProgramFiles/cocos/Quick-Cocos2dx-Community/quick/samples/towerdefense/src/main.lua

------------------------------------------------

还没完
没完
没完呢
找到包含StartupCall::startup()的函数!倒推回去
或者根据

...\quick\player\Classes\AppDelegate.cpp

去找
我们又回到了

bool AppDelegate::applicationDidFinishLaunching()
{
    initResourcePath();
    ...
    StartupCall *call = StartupCall::create(this);
    call->startup();
    
    return true;
}

进入initResourcePath();

void AppDelegate::initResourcePath()
{
    FileUtils* sharedFileUtils = FileUtils::getInstance();
    //设置SearchPaths
    std::vector<std::string> oldSearchPaths = sharedFileUtils->getSearchPaths();
    std::vector<std::string> tempPaths(oldSearchPaths);
    std::vector<std::string> searchPaths;
    searchPaths.push_back(sharedFileUtils->getWritablePath() + "upd/");
    searchPaths.push_back("res/");
    searchPaths.push_back("src/");
    
    for (int i = 0; i < tempPaths.size(); ++i) {
        searchPaths.push_back(tempPaths[i]);
    }
    
    sharedFileUtils->setSearchPaths(searchPaths);
}

亲,你看到了吗?
看到res, src目录的举个爪!!!

4.小结

终于找到了!!
开森!
谢谢观阅,下次再会!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容