前端之家收集整理的这篇文章主要介绍了
cocos2dx-Lua学习笔记:CCLuaStack,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
备注:
1 作者对于Lua的使用较少,纯粹从使用出发,对它的理解较浅,可能有错误,还请路过的各位大牛多多指正。
2 本笔记代码部分参考cocos2dx2.2.3代码,代码版权归原作者所有。
3 由于作者时间,经验,能力有限,笔记可能不完整,以后随用随补充吧。
CCLuaStack代码较多,里面实现了大部分Lua与C++代码的交互细节,这里一点点的笔记吧。
lua_print:
打印栈中的所有的内容。参考网址如下:【 http://cstriker1407.info/blog/lua-basic-notes-stack/】
@H_403_24@
int lua_print(lua_State * luastate) |
@H_403_24@
int nargs = lua_gettop(luastate); |
@H_403_24@
std::string t; |
@H_403_24@
for ( int i=1; i <= nargs; i++) |
@H_403_24@
if (lua_istable(luastate,i)) |
@H_403_24@
else if (lua_isnone(luastate,i)) |
@H_403_24@
else if (lua_isnil(luastate,i)) |
@H_403_24@
else if (lua_isboolean(luastate,i)) |
@H_403_24@
if (lua_toboolean(luastate,i) != 0) |
@H_403_24@
else if (lua_isfunction(luastate,i)) |
@H_403_24@
t += "function" ; |
@H_403_24@
else if (lua_islightuserdata(luastate,i)) |
@H_403_24@
t += "lightuserdata" ; |
@H_403_24@
else if (lua_isthread(luastate,i)) |
@H_403_24@
t += "thread" ; |
@H_403_24@
const char * str = lua_tostring(luastate,i); |
@H_403_24@
t += lua_tostring(luastate,i); |
@H_403_24@
t += lua_typename(luastate,lua_type(luastate,i)); |
@H_403_24@
CCLOG( "[LUA-print] %s" ,t.c_str()); |
创建与初始化:
代码虽然很简短,但是函数调用很多。这里先笔记下最上层的函数调用,底层的函数实现分别笔记。
@H_403_24@
CCLuaStack *CCLuaStack::create( void ) |
@H_403_24@
CCLuaStack *stack = new CCLuaStack(); |
@H_403_24@
stack->init(); |
@H_403_24@
stack->autorelease(); |
@H_403_24@
CCLuaStack *CCLuaStack::attach(lua_State *L) |
@H_403_24@
CCLuaStack *stack = new CCLuaStack(); |
@H_403_24@
stack->initWithLuaState(L); |
@H_403_24@
stack->autorelease(); |
@H_403_24@
bool CCLuaStack::init( void ) |
@H_403_24@
m_state = lua_open(); |
@H_403_24@
luaL_openlibs(m_state); |
@H_403_24@
tolua_Cocos2d_open(m_state); |
@H_403_24@
toluafix_open(m_state); |
@H_403_24@
const luaL_reg global_functions [] = { |
@H_403_24@
{ "print" ,lua_print}, |
@H_403_24@
luaL_register(m_state, "_G" ,global_functions); |
@H_403_24@
tolua_CocoStudio_open(m_state); |
@H_403_24@
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC) |
@H_403_24@
CCLuaObjcBridge::luaopen_luaoc(m_state); |
@H_403_24@
register_all_cocos2dx_manual(m_state); |
@H_403_24@
register_all_cocos2dx_extension_manual(m_state); |
@H_403_24@
register_all_cocos2dx_studio_manual(m_state); |
@H_403_24@
addLuaLoader(cocos2dx_lua_loader); |
@H_403_24@
bool CCLuaStack::initWithLuaState(lua_State *L) |
修改变量package[“path”]:
将新的lua文件路径添加到Lua保存的路径中。参考网址如下:【http://cstriker1407.info/blog/lua-basic-notes-stack-variable-exchange/】
@H_403_24@
void CCLuaStack::addSearchPath( const char * path) |
@H_403_24@
lua_getglobal(m_state, "package" ); |
@H_403_24@
lua_getfield(m_state,-1, "path" ); |
@H_403_24@
const char * cur_path = lua_tostring(m_state,-1); |
@H_403_24@
lua_pushfstring(m_state, "%s;%s/?.lua" ,cur_path,path); |
@H_403_24@
lua_setfield(m_state,-3, "path" ); |
@H_403_24@
lua_pop(m_state,2); |
addLuaLoader:
将自定义的loader方法添加到Lua环境中。
@H_403_24@
void CCLuaStack::addLuaLoader(lua_CFunction func) |
@H_403_24@
if (!func) return ; |
@H_403_24@
lua_getglobal(m_state, "loaders" ); |
@H_403_24@
lua_pushcfunction(m_state,func); |
@H_403_24@
for ( int i = lua_objlen(m_state,-2) + 1; i > 2; --i) |
@H_403_24@
lua_rawgeti(m_state,-2,i - 1); |
@H_403_24@
lua_rawseti(m_state,i); |
@H_403_24@
lua_rawseti(m_state,2); |
@H_403_24@
lua_setfield(m_state, "loaders" ); |
@H_403_24@
lua_pop(m_state,1); |
在Lua中删掉与某个Object有关的注册信息:
@H_403_24@
void CCLuaStack::removeScriptObjectByCCObject(CCObject* pObj) |
@H_403_24@
toluafix_remove_ccobject_by_refid(m_state,pObj->m_nLuaID); |
@H_403_24@
void CCLuaStack::removeScriptHandler( int nHandler) |
@H_403_24@
toluafix_remove_function_by_refid(m_state,nHandler); |
在C中调用Lua脚本:
参考网址如下:【 http://cstriker1407.info/blog/lua-basic-notes-c-call-lua/】
@H_403_24@
int CCLuaStack::executeString( const char *codes) |
@H_403_24@
luaL_loadstring(m_state,codes); |
@H_403_24@
return executeFunction(0); |
@H_403_24@
int CCLuaStack::executeScriptFile( const char * filename) |
@H_403_24@
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) |
@H_403_24@
std::string code( "require \"" ); |
@H_403_24@
code.append(filename); |
@H_403_24@
code.append( "\"" ); |
@H_403_24@
return executeString(code.c_str()); |
@H_403_24@
std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(filename); |
@H_403_24@
++m_callFromLua; |
@H_403_24@
int nRet = luaL_dofile(m_state,fullPath.c_str()); |
@H_403_24@
--m_callFromLua; |
@H_403_24@
CC_ASSERT(m_callFromLua >= 0); |
@H_403_24@
if (nRet != 0) |
@H_403_24@
CCLOG( "[LUA ERROR] %s" ,lua_tostring(m_state,-1)); |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
int CCLuaStack::executeGlobalFunction( const char * functionName) |
@H_403_24@
lua_getglobal(m_state,functionName); |
@H_403_24@
if (!lua_isfunction(m_state,-1)) |
@H_403_24@
CCLOG( "[LUA ERROR] name '%s' does not represent a Lua function" ,functionName); |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
return executeFunction(0); |
@H_403_24@
int CCLuaStack::executeFunction( int numArgs) |
@H_403_24@
int functionIndex = -(numArgs + 1); |
@H_403_24@
if (!lua_isfunction(m_state,functionIndex)) |
@H_403_24@
CCLOG( "value at stack [%d] is not function" ,functionIndex); |
@H_403_24@
lua_pop(m_state,numArgs + 1); |
@H_403_24@
int traceback = 0; |
@H_403_24@
lua_getglobal(m_state, "__G__TRACKBACK__" ); |
@H_403_24@
if (!lua_isfunction(m_state,-1)) |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
lua_insert(m_state,functionIndex - 1); |
@H_403_24@
traceback = functionIndex - 1; |
@H_403_24@
int error = 0; |
@H_403_24@
++m_callFromLua; |
@H_403_24@
error = lua_pcall(m_state,numArgs,1,traceback); |
@H_403_24@
--m_callFromLua; |
@H_403_24@
if (traceback == 0) |
@H_403_24@
CCLOG( "[LUA ERROR] %s" ,- 1)); |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
lua_pop(m_state,2); |
@H_403_24@
if (lua_isnumber(m_state,-1)) |
@H_403_24@
ret = lua_tointeger(m_state,-1); |
@H_403_24@
else if (lua_isboolean(m_state,-1)) |
@H_403_24@
ret = lua_toboolean(m_state,-1); |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
if (traceback) |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
int CCLuaStack::executeFunctionByHandler( int nHandler, int numArgs) |
@H_403_24@
if (pushFunctionByHandler(nHandler)) |
@H_403_24@
if (numArgs > 0) |
@H_403_24@
lua_insert(m_state,-(numArgs + 1)); |
@H_403_24@
ret = executeFunction(numArgs); |
@H_403_24@
lua_settop(m_state,0); |
@H_403_24@
bool CCLuaStack::handleAssert( const char *msg) |
@H_403_24@
if (m_callFromLua == 0) return false ; |
@H_403_24@
lua_pushfstring(m_state, "ASSERT Failed ON LUA EXECUTE: %s" ,msg ? msg : "unknown" ); |
@H_403_24@
lua_error(m_state); |
@H_403_24@
int CCLuaStack::reallocateScriptHandler( int nHandler) |
@H_403_24@
LUA_FUNCTION nNewHandle = -1; |
@H_403_24@
if (pushFunctionByHandler(nHandler)) |
@H_403_24@
nNewHandle = toluafix_ref_function(m_state,lua_gettop(m_state),0); |
@H_403_24@
return nNewHandle; |
@H_403_24@
int CCLuaStack::executeFunctionReturnArray( int nHandler, int nNumArgs, int nNummResults,CCArray* pResultArray) |
@H_403_24@
if (NULL == pResultArray) |
@H_403_24@
if (pushFunctionByHandler(nHandler)) |
@H_403_24@
if (nNumArgs > 0) |
@H_403_24@
lua_insert(m_state,-(nNumArgs + 1)); |
@H_403_24@
int functionIndex = -(nNumArgs + 1); |
@H_403_24@
if (!lua_isfunction(m_state,functionIndex)) |
@H_403_24@
CCLOG( "value at stack [%d] is not function" ,functionIndex); |
@H_403_24@
lua_pop(m_state,nNumArgs + 1); |
@H_403_24@
int traceback = 0; |
@H_403_24@
lua_getglobal(m_state, "__G__TRACKBACK__" ); |
@H_403_24@
if (!lua_isfunction(m_state,-1)) |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
lua_insert(m_state,functionIndex - 1); |
@H_403_24@
traceback = functionIndex - 1; |
@H_403_24@
int error = 0; |
@H_403_24@
++m_callFromLua; |
@H_403_24@
error = lua_pcall(m_state,nNumArgs,nNummResults,traceback); |
@H_403_24@
--m_callFromLua; |
@H_403_24@
if (traceback == 0) |
@H_403_24@
CCLOG( "[LUA ERROR] %s" ,- 1)); |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
lua_pop(m_state,2); |
@H_403_24@
if (nNummResults <= 0) return 0; |
@H_403_24@
for ( int i = 0 ; i < nNummResults; i++) { if (lua_type(m_state,-1) == LUA_TBOOLEAN) { bool value = lua_toboolean(m_state,-1); pResultArray->addObject(CCBool::create(value)) ; |
@H_403_24@
} else if (lua_type(m_state,-1) == LUA_TNUMBER) { |
@H_403_24@
double value = lua_tonumber(m_state,-1); |
@H_403_24@
pResultArray->addObject(CCDouble::create(value)); |
@H_403_24@
} else if (lua_type(m_state,-1) == LUA_TSTRING) { |
@H_403_24@
const char * value = lua_tostring(m_state,-1); |
@H_403_24@
pResultArray->addObject(CCString::create(value)); |
@H_403_24@
pResultArray->addObject( static_cast <ccobject*>(tolua_tousertype(m_state,NULL))); |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
if (traceback) |
@H_403_24@
lua_pop(m_state,1); |
@H_403_24@
lua_settop(m_state,0); |
其中,关于【 __G__TRACKBACK__】,可以查看一下HelloLua工程中的hello.lua文件,有部分内容如下:
@H_403_24@
- - for CCLuaEngine traceback |
@H_403_24@
function __G__TRACKBACK__(msg) |
@H_403_24@
cclog( "----------------------------------------" ) |
@H_403_24@
cclog( "LUA ERROR: " .. tostring(msg) .. "\n" ) |
@H_403_24@
cclog(debug.traceback()) |
@H_403_24@
cclog( "----------------------------------------" ) |
基本类型压栈的处理:
@H_403_24@
void CCLuaStack::clean( void ) |
@H_403_24@
lua_settop(m_state,0); |
@H_403_24@
void CCLuaStack::pushInt( int intValue) |
@H_403_24@
lua_pushinteger(m_state,intValue); |
@H_403_24@
void CCLuaStack::pushFloat( float floatValue) |
@H_403_24@
lua_pushnumber(m_state,floatValue); |
@H_403_24@
void CCLuaStack::pushBoolean( bool boolValue) |
@H_403_24@
lua_pushboolean(m_state,boolValue); |
@H_403_24@
void CCLuaStack::pushString( const char * stringValue) |
@H_403_24@
lua_pushstring(m_state,stringValue); |
@H_403_24@
void CCLuaStack::pushString( const char * stringValue, int length) |
@H_403_24@
lua_pushlstring(m_state,stringValue,length); |
@H_403_24@
void CCLuaStack::pushNil( void ) |
@H_403_24@
lua_pushnil(m_state); |
复杂类型压栈的处理:
@H_403_24@
void CCLuaStack::pushCCObject(CCObject* objectValue, const char * typeName) |
@H_403_24@
toluafix_pushusertype_ccobject(m_state,objectValue->m_uID,&objectValue->m_nLuaID,objectValue,typeName); |
@H_403_24@
void CCLuaStack::pushCCLuaValue( const CCLuaValue& value) |
@H_403_24@
const CCLuaValueType type = value.getType(); |
@H_403_24@
if (type == CCLuaValueTypeInt) |
@H_403_24@
return pushInt(value.intValue()); |
@H_403_24@
else if (type == CCLuaValueTypeFloat) |
@H_403_24@
return pushFloat(value.floatValue()); |
@H_403_24@
else if (type == CCLuaValueTypeBoolean) |
@H_403_24@
return pushBoolean(value.booleanValue()); |
@H_403_24@
else if (type == CCLuaValueTypeString) |
@H_403_24@
return pushString(value.stringValue().c_str()); |
@H_403_24@
else if (type == CCLuaValueTypeDict) |
@H_403_24@
pushCCLuaValueDict(value.dictValue()); |
@H_403_24@
else if (type == CCLuaValueTypeArray) |
@H_403_24@
pushCCLuaValueArray(value.arrayValue()); |
@H_403_24@
else if (type == CCLuaValueTypeCCObject) |
@H_403_24@
pushCCObject(value.ccobjectValue(),value.getCCObjectTypename().c_str()); |
@H_403_24@
void CCLuaStack::pushCCLuaValueDict( const CCLuaValueDict& dict) |
@H_403_24@
lua_newtable(m_state); |
@H_403_24@
for (CCLuaValueDictIterator it = dict.begin(); it != dict.end(); ++it) |
@H_403_24@
lua_pushstring(m_state,it->first.c_str()); |
@H_403_24@
pushCCLuaValue(it->second); |
@H_403_24@
lua_rawset(m_state,-3); |
@H_403_24@
void CCLuaStack::pushCCLuaValueArray( const CCLuaValueArray& array) |
@H_403_24@
lua_newtable(m_state); |
@H_403_24@
int index = 1; |
@H_403_24@
for (CCLuaValueArrayIterator it = array.begin(); it != array.end(); ++it) |
@H_403_24@
pushCCLuaValue(*it); |
@H_403_24@
lua_rawseti(m_state,index); |
@H_403_24@
bool CCLuaStack::pushFunctionByHandler( int nHandler) |
@H_403_24@
toluafix_get_function_by_refid(m_state,nHandler); |
@H_403_24@
if (!lua_isfunction(m_state,-1)) |
@H_403_24@
CCLOG( "[LUA ERROR] function refid '%d' does not reference a Lua function" ,nHandler); |
@H_403_24@
lua_pop(m_state,1); |