主要当年写这个博文,在于说,quick的作者比较厉害,可以直接桥接c++;而cocos2dx的原作者就比较一般了(据说一开始直接抄cocos,全部抄过来已经算"厉害",然后后来重构了75%,这个更"厉害")
是的,我又在反讽,虽然隐藏比较深,但我确实想做出反讽的效果
原文:
有些函数需要向lua返回多个结果,将这些结果存在table中是理所当然的。因为toLua++已经自动生成了函数的wrapper,所以没办法直接将栈顶table返回给Lua。好在toLua预留了lua_Object这个类型,可以代表lua中的任何类型,其实它只是int的typedef罢了,主要是在toLua解析程序时作为标记产生tolua_tovalue调用。在C/C++函数中,需要检查一下栈顶是否为table类型,进行table元素的插入操作,例子函数如下:
void ActorMgr::GetPlayerEntityIDs( lua_Object lua_table )
{
TEntityListIt tIt ;
std::list <int> result;
for(int i = 0; i < ACOTOR_BUCKET_LEN ; ++i)
{
for(tIt =mSceneEntities[i].mEntities.begin(); tIt != mSceneEntities[i].mEntities.end( ); ++tIt )
{
TActorPtr tpActor = tIt->second->mpActor ;
if(tpActor ->GetActorType() == LOCAL_PLAYER)
{
result.push_front(tpActor->GetEntityID());
}
else if (tpActor-> GetActorType() == REMOTE_PLAYER )
{
result.push_back(tpActor->GetEntityID());
}
}
}
lua_State* L = LuaVM::GetInstPtr()->mLS ;
assert(lua_istable (L , -1));
std::list <int>:: iterator iter = result. begin();
for(int i = 1; iter != result .end(); ++ iter , ++i )
{
lua_pushinteger(L , *iter);
lua_rawseti(L , -2 , i);
}
lua_pop(L , 1);
}
ActorMgr::GetPlayerEntityIDs( lua_Object lua_table )
{
TEntityListIt tIt ;
std::list <int> result;
for(int i = 0; i < ACOTOR_BUCKET_LEN ; ++i)
{
for(tIt =mSceneEntities[i].mEntities.begin(); tIt != mSceneEntities[i].mEntities.end( ); ++tIt )
{
TActorPtr tpActor = tIt->second->mpActor ;
if(tpActor ->GetActorType() == LOCAL_PLAYER)
{
result.push_front(tpActor->GetEntityID());
}
else if (tpActor-> GetActorType() == REMOTE_PLAYER )
{
result.push_back(tpActor->GetEntityID());
}
}
}
lua_State* L = LuaVM::GetInstPtr()->mLS ;
assert(lua_istable (L , -1));
std::list <int>:: iterator iter = result. begin();
for(int i = 1; iter != result .end(); ++ iter , ++i )
{
lua_pushinteger(L , *iter);
lua_rawseti(L , -2 , i);
}
lua_pop(L , 1);
}
需要注意的是,如果是多个参数,Lua的压栈顺序是object pointer、参数从左到右,所以栈顶元素是函数签名最右边的参数。
lua转c++
bool luaval_to_size(lua_State* L,int lo,Size* outValue, const char* funcName)
{
if (NULL == L || NULL == outValue)
return false;
bool ok = true;
tolua_Error tolua_err;
if (!tolua_istable(L, lo, 0, &tolua_err) )
{
#if COCOS2D_DEBUG >=1
luaval_to_native_err(L,"#ferror:",&tolua_err,funcName);
#endif
ok = false;
}
if (ok)
{
lua_pushstring(L, "width"); /* L: paramStack key */
lua_gettable(L,lo);/* L: paramStack paramStack[lo][key] */
outValue->width = lua_isnil(L,-1) ? 0 : lua_tonumber(L,-1);
lua_pop(L,1);/* L: paramStack*/
lua_pushstring(L, "height");
lua_gettable(L,lo);
outValue->height = lua_isnil(L,-1) ? 0 : lua_tonumber(L,-1);
lua_pop(L,1);
}
return ok;
}
关于c++如何绑定lua function
int lua_cocos2dx_EventDispatcher_addCustomEventListener(lua_State* tolua_S)
{
int argc = 0;
cocos2d::EventDispatcher* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.EventDispatcher",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::EventDispatcher*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_EventDispatcher_addCustomEventListener'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 2)
{
std::string arg0;
std::function<void (cocos2d::EventCustom *)> arg1;
ok &= luaval_to_std_string(tolua_S, 2,&arg0, "cc.EventDispatcher:addCustomEventListener");
do {
// Lambda binding for lua is not supported.
assert(false);
} while(0)
;
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_EventDispatcher_addCustomEventListener'", nullptr);
return 0;
}
cocos2d::EventListenerCustom* ret = cobj->addCustomEventListener(arg0, arg1);
object_to_luaval<cocos2d::EventListenerCustom>(tolua_S, "cc.EventListenerCustom",(cocos2d::EventListenerCustom*)ret);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.EventDispatcher:addCustomEventListener",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_EventDispatcher_addCustomEventListener'.",&tolua_err);
#endif
return 0;
}