lua_touserdata返回值详释

Lua中使用lua_touserdata处理自定义类型
lua_touserdata函数用于从Lua状态机中获取完整userdata或lightuserdata的指针。当需要处理自定义类型时,可以通过lua_isuserdata检查,并使用二级指针转换获取自定义类型的值。在CCLuaStack的executeFunction函数中,通过添加相应代码,可以处理自定义类型的返回值。对于不熟悉C++二级指针的读者,建议学习相关知识以便理解此过程。

void *lua_touserdata(lua_State*L,intindex);如果给定索引处的值是一个完整的userdata,函数返回内存块的地址。如果值是一个lightuserdata,那么就返回它表示的指针。否则,返回NULL。

例如: 在CCLuaStack::executeFunction()函数中有一段代码是用来获取c++调用lua返回值的。

    // get return value
    int ret = 0;
    if (lua_isnumber(m_state, -1))
    {
        ret = lua_tointeger(m_state, -1);
    }
    else if (lua_isboolean(m_state, -1))
    {
        ret = lua_toboolean(m_state, -1);
    }
 

这个函数只为我们返回了2种类型,如果我们需要返回一些自定义类型(非基本类型),则我们需要这样做:自定义一个返回lua中返回值的函数,在函数中修改上面这段代码加上下面这行代码:

// get return value
    int ret = 0;
    if (lua_isnumber(m_state, -1))
    {
        ret = lua_tointeger(m_state, -1);
    }
    else if (lua_isboolean(m_state, -1))
    {
        ret = lua_toboolean(m_state, -1);
    }

//新添加代码

   else if(lua_isuserdata(m_state, -1))

   {

ret =  *(XXXX**)lua_touserdata(tolua_s, -1);   //XXXX代表自定义类型

   }

至于为什么要这么写->ret =  *(XXXX**)lua_touserdata(tolua_s, -1); 文章一开始就讲清楚了,不懂得恶补一下C++指针(特别是二级指针)的相关知识吧。

好了说了这么多也够详细的了。不明白的可以留言。

你提到的问题是: > `luaText` 没有返回值返回值为 `LUA_TNONE` 这说明你在使用 `luaL_dostring(luaText, str)` 执行 Lua 字符串代码后,期望得到一个返回值,但栈顶是 `LUA_TNONE`(即栈中没有值)。 --- ## 🔍 问题分析 ### 1. `luaL_dostring` 的行为 ```c int luaL_dostring (lua_State *L, const char *str); ``` - 作用:加载并运行一段 Lua 字符串代码。 - 返回值: - `0` 表示成功执行; - 非零表示有错误(比如语法错误、运行时错误等); - **执行完后,Lua 代码的返回值(如果有)会压入栈顶**。 --- ### 2. 为什么栈顶是 `LUA_TNONE`? 因为你的 Lua 代码没有返回值。例如: ```lua -- 没有 return print("Hello World") ``` 执行这段代码后,栈顶是空的(即 `LUA_TNONE`)。 --- ### ✅ 示例说明 #### ✅ 有返回值的情况 ```lua return "Hello from Lua" ``` 执行后,栈顶是一个字符串,`lua_type(L, -1) == LUA_TSTRING`。 #### ❌ 无返回值的情况 ```lua print("Hello from Lua") ``` 执行后,栈顶是空的,`lua_type(L, -1) == LUA_TNONE`。 --- ## ✅ 解决方案 如果你希望 Lua 字符串执行后返回一个值到 C 层,**必须显式使用 `return`**。 ### ✅ 修改 Lua 代码 确保 Lua 字符串以 `return` 结尾: ```c BYTE script[] = "return \"Hello from Lua\""; ``` 或者动态添加 `return`: ```c BYTE new_script[2048]; sprintf(new_script, "return %s", str); // 在 Lua 代码前加上 return ``` 然后执行: ```c if (luaL_dostring(luaText, new_script)) { // 错误处理 } ``` --- ## ✅ 完整修正后的代码示例 ```c INT LuaRunString(lua_State *luaText, BYTE *str) { COM_ASSERT_RET(NULL != luaText, FAILED); BYTE errorString[128] = ""; BYTE new_script[2048]; // 确保足够大 // 在 Lua 脚本前面加上 return,确保返回值被压栈 sprintf(new_script, "return %s", str); if (luaL_dostring(luaText, new_script)) { // 获取错误信息 const char *err = lua_tostring(luaText, -1); sprintf(errorString, "cannot load and run lua script: %s", err ? err : "unknown error"); LogError(errorString); return FAILED; } // 此时栈顶应该有一个返回值 int type = lua_type(luaText, -1); printf("Return value type: %d\n", type); return SUCCESS; } ``` --- ## ✅ 常见类型值说明(`lua_type`) | 类型值 | 宏定义 | 含义 | |--------|----------------|------------------| | 0 | `LUA_TNONE` | 无效位置(栈顶为空) | | 1 | `LUA_TNIL` | `nil` | | 2 | `LUA_TBOOLEAN` | 布尔值 | | 3 | `LUA_TLIGHTUSERDATA` | 轻量级用户数据 | | 4 | `LUA_TNUMBER` | 数字(int/float)| | 5 | `LUA_TSTRING` | 字符串 | | 6 | `LUA_TTABLE` | 表 | | 7 | `LUA_TFUNCTION`| 函数 | | 8 | `LUA_TUSERDATA`| 完整 userdata | | 9 | `LUA_TTHREAD` | 协程 | --- ## ✅ 总结 | 问题 | 原因 | 解决方案 | |------|------|-----------| | 栈顶是 `LUA_TNONE` | Lua 代码没有 `return` 语句 | 在 Lua 代码中加上 `return` | | 执行后栈为空 | Lua 脚本没有返回值 | 动态拼接 `"return "` 前缀 | | 获取不到返回值 | Lua 没有返回值压栈 | 确保 Lua 有 `return` | --- ##
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值