使用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.小结
终于找到了!!
开森!
谢谢观阅,下次再会!