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:
    

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:
    

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 oldSearchPaths = sharedFileUtils->getSearchPaths();
    std::vector tempPaths(oldSearchPaths);
    std::vector 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.小结

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

你可能感兴趣的:(quick cocos2dx-lua引擎怎样找到main.lua函数?)