加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

cocos2d tolua C++对象使用lua对象的变量,函数

发布时间:2020-12-14 16:57:22 所属栏目:百科 来源:网络整理
导读:C++对象绑定到lua通常是创建一个userdata用来存放cpp对象。在tolua库中维护了一张表: tolua_ubox表,它 是个弱表,用来缓存所有cppobj的ptr-userdata映射。 userdata对象的生成过程和cpp对象到userdata的映射的生成。 void tolua_pushusertype_internal (lu

C++对象绑定到lua通常是创建一个userdata用来存放cpp对象。在tolua库中维护了一张表:tolua_ubox表,它是个弱表,用来缓存所有cppobj的ptr->userdata映射。

userdata对象的生成过程和cpp对象到userdata的映射的生成。

void tolua_pushusertype_internal (lua_State* L,void* value,const char* type,int addToRoot)
{
if (value == NULL)
lua_pushnil(L);
else
{
luaL_getmetatable(L,type); /* stack: mt */
if (lua_isnil(L,-1)) { /* NOT FOUND metatable */
lua_pop(L,1);
return;
}
lua_pushstring(L,"tolua_ubox");
lua_rawget(L,-2); /* stack: mt ubox */

//现在每个metatable都维护了一份tolua_ubox表,在类的生成过程,就会为metatable生成这个tolua_ubox表,具体请看mapinheritance和set_ubox
if (lua_isnil(L,-1)) {
lua_pop(L,1);
lua_pushstring(L,"tolua_ubox");
lua_rawget(L,LUA_REGISTRYINDEX); 在创建tolua环境就会创建注册表中的tolua_ubox表
};

lua_pushlightuserdata(L,value); /* stack: mt ubox key<value> */
lua_rawget(L,-2); /* stack: mt ubox ubox[value] */
//查看在mt中的ubox表中是否存在value(C++对象),如果不存在,创建一个,并设置值为userdata,值为value。
if (lua_isnil(L,-1))
{
lua_pop(L,1); /* stack: mt ubox */
lua_pushlightuserdata(L,value);
*(void**)lua_newuserdata(L,sizeof(void *)) = value; /* stack: mt ubox value newud */

//newud就是userdata
lua_pushvalue(L,-1); /* stack: mt ubox value newud newud */
lua_insert(L,-4); /* stack: mt newud ubox value newud */
lua_rawset(L,-3); /* ubox[value] = newud,stack: mt newud ubox */ 映射
lua_pop(L,1); /* stack: mt newud */
/*luaL_getmetatable(L,type);*/
lua_pushvalue(L,-2); /* stack: mt newud mt */
lua_setmetatable(L,-2); /* update mt,stack: mt newud */ 设置userdata的metatable为cpp的metatable。

#ifdef LUA_VERSION_NUM
lua_pushvalue(L,TOLUA_NOPEER); /* stack: mt newud peer */
lua_setfenv(L,-2); /* stack: mt newud */ 设置userdata的环境为TOLUA_NOPEER
#endif
}
else
{
//.....
}
}

那这和C++对象使用lua对象的函数,变量有什么关系呢?

其实一直在纠结lua对象继承C++对象的这个问题,到今天才看到比较满意的解决办法。

function cls.extend(target,...) //target是个C++对象来的
-- 先继承C++对象
local t = tolua.getpeer(target)
if not t then
t = {}
tolua.setpeer(target,t)
end
setmetatable(t,cls)
cls.ctor(target,...)
return target
end

在网上其实存在很多这个例子。

知其然不知其然怎么行呢?

tolua_getpeer和tolua_setpeer是什么鬼:

static int tolua_bnd_getpeer(lua_State* L) {


/* stack: userdata */
lua_getfenv(L,-1);
if (lua_rawequal(L,-1,TOLUA_NOPEER)) { 在上面的描述中,userdata的环境就是TOLUA_NOPEER,所以这边会返回空
lua_pop(L,1);
lua_pushnil(L);
};
return 1;
};


static int tolua_bnd_setpeer(lua_State* L) {


/* stack: userdata,table */
if (!lua_isuserdata(L,-2)) {
lua_pushstring(L,"Invalid argument #1 to setpeer: userdata expected.");
lua_error(L);
};


if (lua_isnil(L,-1)) {


lua_pop(L,1);
lua_pushvalue(L,TOLUA_NOPEER);
};
lua_setfenv(L,-2); 为userdata设置新的环境


return 0;
};


所以例子中的

local t = tolua.getpeer(target)
if not t then
t = {}
tolua.setpeer(target,t)
end

这段是为了给这个C++对象(userdata)设置一个新的环境。这个环境现在什么都没有

setmetatable(t,cls) 现在这个环境中有了cls,这个cls就是Lua table。可以看做是我们的lua对象,lua class

然后返回C++对象。这样就可以通过C++对象使用到lua对象中的所有内容。其实在lua文件中可以创建这样的C++对象,既可以使用这个对象原有的东西还可以使用我们的lua内容,其实换个思路想想,如果把返回的对象看做是lua对象,这也就是lua对象继承C++对象嘛。


范例:

local tt = cc.Node:create()
local env = {}
env.abc = 4
env.func = function()
print("环境函数") //输出环境函数 end local peer = tolua.getpeer(tt) if not peer then tolua.setpeer(tt,env) print(tt.abc) //输出4 tt.func() end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读