Что такое userdata и lightuserdata в Lua? - PullRequest
25 голосов
/ 02 декабря 2010
  • Что такое userdata и lightuserdata в Lua?
  • Где мне это нужно?

Я уже некоторое время пытаюсь обернуть голову вокруг этого, но я не могу найти какие-либо учебники / объяснения, которые я действительно понимаю.

Зачем они вам нужны, почему вы не можете просто напрямую связать функции C с метатаблицами Lua?

Ответы [ 4 ]

50 голосов
/ 02 декабря 2010

Пользовательские данные - это значение произвольного размера и содержимого, собираемое мусором.Вы создаете один из C API с lua_newuserdata(), который создает и помещает его в стек и дает вам указатель на его содержимое для инициализации, как вы считаете нужным из C.

Это очень сравнимо с звонком malloc().Ключевым отличием от malloc() является то, что вам никогда не нужно вызывать free(), скорее вы просто позволяете последней ссылке на него испариться, и сборщик мусора в конечном итоге восстановит свое хранилище.

Они наиболее полезны дляхранение данных, которые полезны из C, но которыми нужно управлять из Lua.Они поддерживают отдельные метатаблицы, которые являются ключевой функцией, которая позволяет связывать объекты C или C ++ с Lua.Вы просто заполняете его метатаблицу методами, написанными на C, которые осуществляют доступ, изменяют и / или используют содержимое пользовательских данных, и в результате получается объект, доступный из Lua.Хорошим примером этого является io библиотека , которая хранит указатели C FILE * в пользовательских данных и обеспечивает привязки, которые реализуют знакомые read, write и подобные методы.Реализуя метаметод __gc, библиотека io гарантирует, что один из ее file объектов закрывает связанный FILE * при его сборе.

Легкие пользовательские данные - это способ представления указателя начто-то как ценность в Lua.Вы создаете его, вызывая lua_pushlightuserdata() с указателем, который является его значением.Они управляются Lua так же, как число.Они полезны, когда вам нужно назвать объект C так, чтобы это имя можно было передать в Lua, но Lua не управляет временем жизни объекта.Как числа равны, когда они имеют одинаковое значение, легкие пользовательские данные сравниваются равными, когда они держат один и тот же указатель.Как и числа, они существуют до тех пор, пока они находятся в стеке или хранятся в переменной, и у них нет отдельных метатаблиц, и они не являются сборщиком мусора.

7 голосов
/ 02 декабря 2010

Ну, userdata - это данные со стороны C, которые можно использовать из Lua.Например, дескрипторы файлов, такие как io.input, являются userdata (попробуйте print (type (io.input))).Он вам понадобится сам, если вы начнете возиться с Lua C-API (или воспользуетесь функцией newproxy, которая даст вам пустой пользовательский набор данных, для которого вы можете установить метатабельный тип (см. Скрытые функции http://lua -users).org / wiki / HiddenFeatures ) на вики-сайте Lua-пользователей).

Хорошее введение: http://www.lua.org/pil/28.html

Что касается вещей с функциями C: да, вы можете просто зарегистрироватьсяФункции C - это функции, которые вызываются из Lua, но это не даст вам других типов данных, указателей на данные на стороне C и т. Д. И т. Д.

2 голосов
/ 27 июля 2015

Во-первых, userdata означает полные userdata. Вот два решения для реализации CharArray. Пожалуйста, смотрите ниже:

//full userdata 
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;
}

//light userdata 
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;
}

Полные пользовательские данные - это необработанная область памяти без предопределенных операций , предлагаемая Lua . Таким образом, пользовательские данные должны управляться сборщиком мусора. С другой стороны, легкие userdata - это просто значение, представляющее указатель C (то есть значение void *). Легкие пользовательские данные не должны управляться сборщиком мусора (и не являются им).

2 голосов
/ 02 декабря 2010

вы можете использовать userdata Всякий раз, когда у вас есть некоторый объем данных, которыми вы хотите управлять с помощью lua gc.Например, вы можете использовать его для объектов C ++.Несколько примеров для c ++ - объектов с userdata: вы можете сохранить один в userdata, затем вы можете забыть об этом в C ++, так как он будет управляться lua.Таким образом, вы можете ссылаться на него в luavariables и передавать его функциям, которые вызывают функцию-член объекта c ++.(Есть способы обобщить это, как, например, поместить объект универсальной функции в данные пользователя, связать его как значение с C-замыканием и зарегистрировать это c-замыкание в объекте lua, который представляет сторону lua объекта c ++, что включаетuserdata также).Если вы не хотите, чтобы lua gc управлял вашими объектами, и просто хотите сослаться на ваш объект c ++ из lua, вы можете сохранить указатель на него в виде легких пользовательских данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...