栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Cocos2dx的Lua与C++交互

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Cocos2dx的Lua与C++交互

文章目录
  • Cocos2dx里Lua与C是怎样交互的?
    • 一、Lua2C
      • 1.从初始化一个主线程(协程)开始:
      • 2.进入register_all_cocos2dx
      • 3.进入lua_register_cocos2dx_Ref

今天的面试有被问到Lua与C的调用,一时也没说出个123来,回来抓紧补一下,嘻嘻


Cocos2dx里Lua与C是怎样交互的? 一、Lua2C 1.从初始化一个主线程(协程)开始:
bool LuaStack::init(void)
{
	_state = lua_open();
	...
	register_all_cocos2dx(_state);
	...
}

我们注意到了register_all_cocos2dx这个func,主要是注册所有Cocos2dx基本的类到Lua里

2.进入register_all_cocos2dx
  • tolua_open
    注册Cocos方法前的准备工作
TOLUA_API void tolua_open (lua_State* L)
{
    int top = lua_gettop(L);
    //将tolua_opened压入栈
    lua_pushstring(L,"tolua_opened");
    //获取LUA_REGISTRYINDEX,然后取栈顶元素k(tolua_open),t[k]入栈顶
    lua_rawget(L,LUA_REGISTRYINDEX);
    if (!lua_isboolean(L,-1))
    {
    	//压入字符串tolua_opened
        lua_pushstring(L,"tolua_opened");
        //压入bool值1
        lua_pushboolean(L,1);
        //获取注册表t,取栈顶bool与字符串tolua_opened,t[tolua_opened]=1
        lua_rawset(L,LUA_REGISTRYINDEX);
        
        // create value root table
        //压入字符串TOLUA_VALUE_ROOT
        lua_pushstring(L, TOLUA_VALUE_ROOT);
        //创建table
        lua_newtable(L);
        //t[TOLUA_VALUE_ROOT] = table
        lua_rawset(L, LUA_REGISTRYINDEX);

#ifndef LUA_VERSION_NUM 
        
        lua_pushstring(L, "tolua_peers");
        lua_newtable(L);
        
        lua_newtable(L);//table1
        lua_pushliteral(L, "__mode");
        lua_pushliteral(L, "k");
        //table1[__model] = k
        lua_rawset(L, -3);                
        //setmetatable(table,table1)
        lua_setmetatable(L, -2);   
        lua_rawset(L,LUA_REGISTRYINDEX);
#endif
	......
    }
    lua_settop(L,top);
}

  • tolua_module
TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
{
    if (name)
    {
        
        lua_pushstring(L,name);
        lua_rawget(L,-2);
        //判断_G[name]~=nil
        if (!lua_istable(L,-1))  
        {
        	//弹出刚才的空value
            lua_pop(L,1);
            //创建空表stack:_G,table
            lua_newtable(L);
            //压栈name stack:_G,table,name
            lua_pushstring(L,name);
            //拷贝栈顶-2上面的table stack:_G,table,name,tablecopy
            lua_pushvalue(L,-2);
            //tablecopy[name] = table stack:_G,table
            lua_rawset(L,-4);       
        }
    }
    else
    {
        
        lua_pushvalue(L,LUA_GLOBALSINDEX);
    }
    //设置元表的过程
    if (hasvar)
    {
        if (!tolua_ismodulemetatable(L))  
        {
            
            lua_newtable(L);
            tolua_moduleevents(L);
            if (lua_getmetatable(L,-2))
                lua_setmetatable(L,-2);  
            lua_setmetatable(L,-2);
        }
    }
    lua_pop(L,1);               
}
  • tolua_beginmodule
    判断这个table的isclass,不是的话返回table;是的话返回他的元表
TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
{
    if (name) { // ... module
//---- now module[name] is a table, get it's metatable to store keys
        // get module[name]
        lua_pushstring(L,name); // ... module name
        lua_rawget(L,-2);       // ... module module[name]
        // Is module[name] a class table?
        lua_pushliteral(L, ".isclass");
        lua_rawget(L, -2);                  // stack: ... module module[name] class_flag
        //判断是否是一个class table:isclass == true
        if (lua_isnil(L, -1)) {
        	//返回table
            lua_pop(L, 1);                  // stack: ... module module[name]
            return;                         // not a class table, use origin table
        }
        lua_pop(L, 1);                      // stack: ... module class_table
        // get metatable
        if (lua_getmetatable(L, -1)) {  // ... module class_table mt
        	//返回table的mt
            lua_remove(L, -2);          // ... module mt
        }
//---- by SunLightJuly, 2014.6.5
    } else {
        lua_pushvalue(L,LUA_GLOBALSINDEX);
    }
}
3.进入lua_register_cocos2dx_Ref
  • tolua_usertype
TOLUA_API void tolua_usertype (lua_State* L, const char* type)
{
    char ctype[128] = "const ";
    strncat(ctype,type,120);

    
    //这里创建了两个元表
    //执行  与set classname 操作
    if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type))
    	//下面分析
        mapsuper(L,type,ctype);             
}

  • mapsuper
    设置连个的继承关系
static void mapsuper (lua_State* L, const char* name, const char* base)
{
    
    lua_pushstring(L,"tolua_super");
    //获取super
    lua_rawget(L,LUA_REGISTRYINDEX);    
    //注册表R里获取名为name的元表
    luaL_getmetatable(L,name);          
    //获取tolua_super[mt]
    lua_rawget(L,-2);                   
    //如果是空的
    if (lua_isnil(L,-1))
    {
        
        lua_pop(L,1);
        lua_newtable(L);                    
        luaL_getmetatable(L,name);          
        lua_pushvalue(L,-2);                
        lua_rawset(L,-4);                   
        //相当于super[mt] = table
    }

    
    lua_pushstring(L,base);
    lua_pushboolean(L,1);
    lua_rawset(L,-3);                    

    
    //基类的k-v 复制到 name元表
    luaL_getmetatable(L,base);          
    lua_rawget(L,-3);                   
    if (lua_istable(L,-1))
    {
        
        lua_pushnil(L);  
        while (lua_next(L,-2) != 0)
        {
            
            lua_pushvalue(L,-2);    
            lua_insert(L,-2);       
            lua_rawset(L,-5);       
        }
    }
    lua_pop(L,3);                       
}

  • tolua_cclass
    主要建立父子类的关系
mapinheritance(L,name,base);

mapinheritance(L,cname,name);

mapsuper(L,cname,cbase);

mapsuper(L,name,base);
  • tolua_function
    注册C方法到栈顶

针对文档、注释、已经一些大哥的帖子做出的自己对于这个过程的注释。
如果哪里有问题,欢迎指正,谢谢。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1009479.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号