userdata和lightuserdata在Lua中是什么?
- 什么是 Lua 中的 userdata 和 lightuserdata?
- 在哪里需要使用它?
我一直在努力理解它,但似乎找不到我真正理解的教程/解释。
你为什么需要它们,为什么不能直接将 C 函数绑定到 Lua 元表上?
原文链接 https://stackoverflow.com/questions/4329643
当您有一些数据需要由 Lua GC 管理时,您可以使用 userdata。例如,您可以将其用于 C++ 对象。一些包含 userdata 的 C++ 对象示例:您可以将一个 C++ 对象保存在 userdata 中,然后在 C++ 中忘记它,因为它将由 Lua 管理。因此,您可以在 Lua 变量中引用它,并将其传递给调用 C++ 对象成员函数的函数。当然,还有一些通用的方法,例如在 userdata 中放置一个通用函数对象,将其绑定为 C 闭包的上值,并将该 C 闭包注册到代表 C++ 对象的 Lua 对象上(这也涉及到 userdata)。
如果您不希望 Lua GC 管理您的对象,只想从 Lua 中引用您的 C++ 对象,您可以将指向它的指针存储为轻量级 userdata。
一个userdata是一个任意大小和内容的垃圾回收值。您可以通过C API创建一个userdata,使用lua_newuserdata()
创建并推送它到堆栈,并给出一个指向其内容的指针,以便您可以自由地从C初始化。
它非常类似于调用malloc()
。与malloc()
的一个重要区别是,您不需要调用free()
,而只是允许最后一个对其的引用消失,垃圾回收器最终将回收它的存储空间。
它们最有用的是用于保留从Lua管理但从C中有用的数据。它们支持单个元表,这是绑定C或C++对象到Lua的关键特性。您只需使用C编写的方法填充其元表,方法可以访问,修改和/或使用userdata的内容,结果是可从Lua访问的对象。一个很好的例子是io
库,它将C的FILE *
指针存储在userdata中,并提供绑定其实现的熟悉的read
,write
和类似的方法。通过实现一个__gc
元方法,io
库确保其中一个file
对象在被收集时关闭关联的FILE *
。
一个轻量级的userdata是您如何将指针表示为Lua中的值。您可以通过调用lua_pushlightuserdata()
使用指针作为它的值创建一个light userdata。它们受Lua的管理方式与数字非常相似。当您需要以某种方式在Lua中命名C对象的名称,但对象的生存期不受Lua控制时,它们非常有用。当它们保持相同指针时,与数字相同,它们相等。像数字一样,只要它们在堆栈中或存储在变量中,它们将一直存在,而它们没有单个元表并且它们不会被垃圾回收。
首先,userdata
表示完全的用户数据。下面是两个实现 CharArray
的解决方案。具体请看下面的代码:
// 完全的用户数据
extern "C" int newarray(lua_State* L)
{
int n = luaL_checkint(L, 1);
size_t nbytes = sizeof(CharArray) + (n - 1)*sizeof(char);
CharArray* a = (CharArray*)lua_newuserdata(L, nbytes);
a->size = n;
return 1;
}
// 轻量的用户数据
extern "C" int newlarray(lua_State* L)
{
int n = luaL_checkint(L, 1);
size_t nbytes = sizeof(CharArray) + (n - 1)*sizeof(char);
CharArray* a = (CharArray*)(new char(nbytes));
lua_pushlightuserdata(L,a);
a->size = n;
return 1;
}
完全的 userdata
是一个没有任何预定义操作的原始内存区域,必须由垃圾回收器进行管理。另一方面,轻量级的 userdata
只是一个表示 C 指针的值(即 void *
值)。轻量级的 userdata
不需要由垃圾收集器进行管理(因此也不会管理)。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
好的,userdata 是从 C 侧获取的数据,可以在 Lua 中使用。例如,像 io.input 这样的文件句柄是 userdata(尝试 print(type(io.input)))。如果您开始与 Lua C-API 搞混或使用 newproxy 函数,则需要自己使用它,后者会在其中提供一个空的 userdatum,您可以在其上设置 metatable(请参见 Hidden Features http://lua-users.org/wiki/HiddenFeatures)在 Lua-users 维基上)。
一个很好的介绍是: http://www.lua.org/pil/28.html
至于 C 函数的内容:是的,您可以将 C 函数注册为从 Lua 内部调用的函数,但它不会让您获得其他数据类型、指向 C 端数据的指针等等。