C++导入自定义类到lua的详细分析

本文详细介绍了如何将C++的自定义类注册并导入到Lua中,通过register_all_moonton函数,利用lua_state将类绑定到Lua中,涉及到lua的元表创建、函数绑定等关键步骤,帮助读者理解C++与Lua交互的底层机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

最近抽空看了下c++导出自定义类到lua中的一些底层实现,在这里记录,一方面方便自己以后查阅,另一方面也可以为他人提供一些思路(文章中如有错误,欢迎指正)

研究环境:

vs2012,cocos2dx-3.2,lua 5.3

一些有用的参考网站:

[Lua5.3 reference manual](http://www.lua.org/manual/5.3/manual.html)

正文:

先从入口讲起,在这里,关于lua的初始化、lua_state的初始化之类的就不再阐述了,这方面也是挺大的,有兴趣的可以搜索关于它们的相关文章。这里我们直接看关于本文的比较核心的代码段:
    cocos2d::LuaEngine* pEngine = cocos2d::LuaEngine::getInstance();
    cocos2d::ScriptEngineManager::getInstance()->setScriptEngine(pEngine);
    cocos2d::LuaStack* stack = pEngine->getLuaStack();
    stack->setLuaErrorCB( onLuaError );
    register_all_moonton( stack->getLuaState() );

其中 最后一个函数,register_all_moonton这个函数就是注册一些自定义类到lua中,其中就有我着重研究的类,其实现如下:

TOLUA_API int register_all_moonton(lua_State* tolua_S)
{
    tolua_open(tolua_S);

    tolua_module(tolua_S,nullptr,0);
    tolua_beginmodule(tolua_S,nullptr);

    lua_register_moonton_CGameFunc(tolua_S);

    tolua_endmodule(tolua_S);
    return 1;
}

这个函数接受一个lua_state指针作为参数,关于lua_state,可以理解为lua的一种多线程,深入的细节有兴趣的同学可以查阅相关文章,在本文中你可以暂时把它当做一个“栈”来看待。
下面我们一步步看整个导入流程:(遇到不知道的lua api,可以去上面提供的manual手册里面进行查找,英语不太好的同学,开着词典屏幕取词也是可以大概看懂的,里面的解释都很易懂)

tolua_open(tolua_S);

打开相应实现:

TOLUA_API void tolua_open (lua_State* L)
{
    int top = lua_gettop(L);//获取栈顶编号(因为index从1开始,所以变相等于获取栈上面一共有多少元素)
    lua_pushstring(L,"tolua_opened");//将“tolua_opened”字符串压入栈,此时栈结构:stack:“tolua_opened”
    lua_rawget(L,LUA_REGISTRYINDEX);//获取名为LUA_REGISTRYINDEX的表t,然后取栈顶元素k,弹出栈顶元素k,然后将值t[k]压入栈顶,此时栈结构:stack:value
    if (!lua_isboolean(L,-1))//这里是重复初始化,以后会把tolua_opened置为true,这里-1指的是栈顶,关于栈的正负索引,下面给图,这里判断栈顶是否为bool值
    {
        lua_pushstring(L,"tolua_opened");//将“tolua_opened”压入栈,此时栈结构:stack:value “tolua_opened”
        lua_pushboolean(L,1);//将1当做一个bool值压入栈,此时栈结构:value “tolua_opened” 1
        lua_rawset(L,LUA_REGISTRYINDEX);//获取lua注册表t,栈顶元素作为value,栈顶后面一个作为key,t[key]=value,弹出value和key,此时栈结构:stack:value

        // create value root table
        lua_pushstring(L, TOLUA_VALUE_ROOT);//string压入栈,栈结构:stack:value TOLUA_VALUE_ROOT
        lua_newtable(L);//创建新表,并压入栈,栈结构:value TOLUA_VALUE_ROOT table
        lua_rawset(L, LUA_REGISTRYINDEX);//获取lua注册表t,栈中的table作为value,TOLUA_VALUE_ROOT作为key,实际上等于t[TOLUA_VALUE_ROOT] = table,分别弹出table,TOLUA_VALUE_ROOT,栈结构:stack:value

#ifndef LUA_VERSION_NUM /* only prior to lua 5.1 */
        /* create peer object table */
        lua_pushstring(L, "tolua_peers");//字符串压入栈,栈结构:stack:value "tolua_peers"
        lua_newtable(L);//创建一个新表并压入栈,栈结构:stack:value "tolua_peers" table
        /* make weak key metatable for peers indexed by userdata object */
        lua_newtable(L);//创建一个新表并压入栈,栈结构:stack:value "tolua_peers" table table1
        lua_pushliteral(L, "__mode");//压入一个字符串,栈结构:stack:value "tolua_peers" table table1 "__mode"
        lua_pushliteral(L, "k");//压入一个字符串,栈结构:stack:value "tolua_peers" table table1 "__mode" "k"
        lua_rawset(L, -3);//分别取栈顶元素作为value,下一个作为key,第三个作为t,t[key]=value,并弹出栈顶和第二个元素,(这里实际上是实现table的弱引用)当前栈结构:stack:value "tolua_peers" table table1
        lua_setmetatable(L, -2);//将栈顶table1作为第二个元素table的元表,弹出table1,栈结构:stack:value "tolua_peers" table
        lua_rawset(L,LUA_REGISTRYINDEX);//栈顶元素作为value,第二个元素作为key,lua注册表作为t,t[key]=value,分别弹出栈顶元素、第二个元素,栈结构:stack:value
#endif
        //这里与上面类似,就不在阐述
        /* create object ptr -> udata mapping table */
        lua_pushstring(L,"tolua_ubox");
        lua_newtable(L);
        /* make weak value metatable for ubox table to allow userdata to be
           garbage-collected */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值