2010-12-01 4 views
22
  • Что такое userdata и lightuserdata в Lua?
  • Где это?

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

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

+1

Метатабельный должен быть прикреплен к * something *, userdatum является разумным выбором. – Textmode 2013-08-28 23:49:10

ответ

7

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

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

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

2

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

42

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

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

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

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

+0

+1 для подробного описания об управлении памятью :) – Eonil 2011-06-20 01:50:23

1

Во-первых, 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 должен управляться сборщиком мусора. С другой стороны, легкие пользовательские данные - это просто значение, которое представляет собой указатель C (то есть значение void *). Легкие пользовательские данные не должны управляться сборщиком мусора (а не являются).

Смежные вопросы