userdata和lightuserdata在Lua中是什么?

  • 什么是 Lua 中的 userdata 和 lightuserdata?
  • 在哪里需要使用它?

我一直在努力理解它,但似乎找不到我真正理解的教程/解释。

你为什么需要它们,为什么不能直接将 C 函数绑定到 Lua 元表上?

原文链接 https://stackoverflow.com/questions/4329643

点赞
stackoverflow用户513763
stackoverflow用户513763

好的,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 端数据的指针等等。

2010-12-01 22:14:34
stackoverflow用户97702
stackoverflow用户97702

当您有一些数据需要由 Lua GC 管理时,您可以使用 userdata。例如,您可以将其用于 C++ 对象。一些包含 userdata 的 C++ 对象示例:您可以将一个 C++ 对象保存在 userdata 中,然后在 C++ 中忘记它,因为它将由 Lua 管理。因此,您可以在 Lua 变量中引用它,并将其传递给调用 C++ 对象成员函数的函数。当然,还有一些通用的方法,例如在 userdata 中放置一个通用函数对象,将其绑定为 C 闭包的上值,并将该 C 闭包注册到代表 C++ 对象的 Lua 对象上(这也涉及到 userdata)。

如果您不希望 Lua GC 管理您的对象,只想从 Lua 中引用您的 C++ 对象,您可以将指向它的指针存储为轻量级 userdata。

2010-12-01 22:21:31
stackoverflow用户68204
stackoverflow用户68204

一个userdata是一个任意大小和内容的垃圾回收值。您可以通过C API创建一个userdata,使用lua_newuserdata()创建并推送它到堆栈,并给出一个指向其内容的指针,以便您可以自由地从C初始化。

它非常类似于调用malloc()。与malloc()的一个重要区别是,您不需要调用free(),而只是允许最后一个对其的引用消失,垃圾回收器最终将回收它的存储空间。

它们最有用的是用于保留从Lua管理但从C中有用的数据。它们支持单个元表,这是绑定C或C++对象到Lua的关键特性。您只需使用C编写的方法填充其元表,方法可以访问,修改和/或使用userdata的内容,结果是可从Lua访问的对象。一个很好的例子是io,它将C的FILE *指针存储在userdata中,并提供绑定其实现的熟悉的readwrite和类似的方法。通过实现一个__gc元方法,io库确保其中一个file对象在被收集时关闭关联的FILE *

一个轻量级的userdata是您如何将指针表示为Lua中的值。您可以通过调用lua_pushlightuserdata()使用指针作为它的值创建一个light userdata。它们受Lua的管理方式与数字非常相似。当您需要以某种方式在Lua中命名C对象的名称,但对象的生存期不受Lua控制时,它们非常有用。当它们保持相同指针时,与数字相同,它们相等。像数字一样,只要它们在堆栈中或存储在变量中,它们将一直存在,而它们没有单个元表并且它们不会被垃圾回收。

2010-12-02 07:34:55
stackoverflow用户3752499
stackoverflow用户3752499

首先,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 不需要由垃圾收集器进行管理(因此也不会管理)。

2015-07-27 07:15:26