Подтвердить что ты не робот

Что такое userdata и lightuserdata в Lua?

  • Что такое userdata и lightuserdata в Lua?
  • Где мне это нужно?

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

Во-первых, 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;
}

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