Создание Lua-глобалов в Objective C / C из userdata

Я работаю над библиотекой, чтобы разрешить Lua (5.2) скрипты игр в iOS 5.x. Я создал класс и добавил привязки, чтобы он можно было создать и получить доступ к форме Lua. Метод инициализатора C, вызванный из Lua, приведен ниже:

static int newGeminiObject(lua_State *L){ GeminiObject *go = [[GeminiObject alloc] initWithLuaState:L]; GeminiObject **lgo = (GeminiObject **)lua_newuserdata(L, sizeof(GeminiObject *)); *lgo = go; luaL_getmetatable(L, GEMINI_OBJECT_LUA_KEY); lua_setmetatable(L, -2); lua_newtable(L); lua_setuservalue(L, -2); NSLog(@"New GeminiObject created"); // add this new object to the globall list of objects [[Gemini shared].geminiObjects addObject:go]; return 1; } 

Это назначает метатет, который настроен в другом месте для обеспечения доступа к различным методам. Кроме того, он прикрепляет таблицу как служебную информацию, позволяющую сценарию сценария назначать атрибуты объектам.

Я могу создать эти объекты в сценариях Lua без проблем:

 require "gemini" x = gemini.new() x:addEventListener("touch", objectTouched) 

Здесь objectTouched – метод aa Lua, определенный в другом месте, который обрабатывает событие касания. Здесь addEventListener связывает его, чтобы touch событий.

Эти объекты работают очень хорошо. Однако, когда я пытаюсь создать один из C, у меня возникают проблемы. Я могу создать объект, но пытаюсь назначить его глобальному, а затем вызывать его в скрипте.

Выполняется следующий код C

 -(void) addRuntimeObject { GeminiObject *rt = [[GeminiObject alloc] initWithLuaState:L]; GeminiObject **lruntime = (GeminiObject **)lua_newuserdata(L, sizeof(GeminiObject *)); *lruntime = rt; // set the metatable - effectively declaring the type for this object luaL_getmetatable(L, GEMINI_OBJECT_LUA_KEY); lua_setmetatable(L, -2); // add a table to hold anything the user wants to add lua_newtable(L); lua_setuservalue(L, -2); // create an entry in the global table lua_setglobal(L, "Runtime"); // empty the stack lua_pop(L, lua_gettop(L)); } 

Это должно определить глобальное имя «Runtime». Пытаясь получить доступ к этой переменной из сценария, подобного этому

 Runtime:addEventListener("enterFrame", enterFrame) 

Результаты со следующей ошибкой:

attempt to index global 'Runtime' (a userdata value)

Это значение userdata, но это не кажется важным, когда я создаю его в Lua напрямую. Метатизируемое связывание обеспечивает доступ к методам и метаметодам. Опять же, это отлично работает, если объект создан из Lua, а не когда он создан на C.

Любые идеи относительно того, что я делаю неправильно здесь, или то, что правильный способ сделать глобальным из userdata?

РЕДАКТИРОВАТЬ

Основываясь на комментариях ниже относительно путаницы в отношении GEMINI_OBJECT_LUA_KEY, я думал, что перечислил код, который фактически используется в привязке:

 static const struct luaL_Reg geminiObjectLib_f [] = { {"new", newGeminiObject}, {NULL, NULL} }; static const struct luaL_Reg geminiObjectLib_m [] = { {"addEventListener", addEventListener}, {"__gc", geminiObjectGC}, {"__index", l_irc_index}, {"__newindex", l_irc_newindex}, {NULL, NULL} }; int luaopen_geminiObjectLib (lua_State *L){ // create the metatable and put it into the registry luaL_newmetatable(L, GEMINI_OBJECT_LUA_KEY); lua_pushvalue(L, -1); // duplicates the metatable luaL_setfuncs(L, geminiObjectLib_m, 0); // create a table/library to hold the functions luaL_newlib(L, geminiObjectLib_f); NSLog(@"gemini lib opened"); return 1; } 

Этот код регистрирует библиотеку функций (не показаны здесь), которые предоставляют методы и метаметоды для GeminiObjects . Вызов luaL_newmetatable создает новый метатебель и связывает его в реестре с ключом GEMINI_OBJECT_LUA_KEY . GEMINI_OBJECT_LUA_KEY – это просто уникальная строка, определенная в заголовке. luaL_setfuncs фактически добавляет указатели на функции к метатегам, делая их доступными как методы объектов.

One Solution collect form web for “Создание Lua-глобалов в Objective C / C из userdata”

В случае, если кто-то все еще интересуется, я получил ответ на свой вопрос от добрых людей в списке рассылки Lua. Проблема здесь в том, что функция привязки библиотеки luaopen_geminiObjectLib не вызывается перед моим вызовом addRuntimeObject .

Поскольку iOS не поддерживает динамические библиотеки, я добавил свои библиотеки в статически, добавив указатели на них в массив linit.c в linit.c источника Lua. К сожалению, библиотеки, добавленные таким образом, не загружаются до тех пор, пока не require('libname') в сценарии Lua. Поскольку я вызывал свой метод addRuntimeObject до выполнения сценария Lua, библиотека еще не была загружена.

Решение состоит в том, чтобы добавить указатель на luaopen_geminiObjectLib в массив loadedlibs в том же файле linit.c . Это приводит к загрузке библиотеки при запуске Lua без необходимости использования сценариев.

  • Приложение iOS не построено в Corona
  • Interesting Posts

    Есть ли способ получить доступ к воспроизводимой в настоящий момент треку, когда iPhone подключен к аксессуару?

    Есть ли способ получить доступ к таким выводам, как availableInputs в AVAudioSession

    Splitviewcontroller с двумя табличными представлениями, делегировать проблему

    Как получить правильную широту и долготу с загруженной фотографии iPhone?

    Почему сигнал вызывается дважды в ReactiveCocoa?

    Как разобрать этот ответ Flickr?

    NSPredicate с динамическим ключом и значением

    Добавить кнопки в подкласс UINavigationController

    Как установить текст на одной странице и изображение на другой странице в UIPageViewController

    Центрирование UIBarButtonItem в UIToolbar и добавление пользовательского текста

    Как обойти / обработать делегирование ошибок EXC_BAD_ACCESS? Obj C

    Запрос GeoFire на местоположение пользователя

    Срок истечения срока действия кода TestFlight

    NSTimer не запускает селектор

    NSUserActivity отсутствует свойство contentAttributeSet

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.