Эквивалент Lua coroutine.create в С++ с использованием lua_newthread

3 Steve [2012-07-08 03:05:00]

У меня есть система обратного вызова, которая может добавлять функции lua в обработчик С++, например. в lua я могу сделать

myCObject:AddCallback(luaFunc)

i также имеет то же значение для сопрограмм

myCObject:AddCallback(coroutine.create(luaFunc))

Затем я могу использовать

lua_State * pThread = lua_tothread(L, -1);
lua_resume(pThread, 0,0);

в С++

Чтобы запустить/возобновить функцию lua.

Теперь я не хочу, чтобы script писатели писали coroutine.create(luaFunc) - и я просто хочу автоматически "преобразовать" lua func в сопрограмму. Когда вызывается AddCallback, у меня есть luaFunc в стеке - и как я могу продолжить? (с coroutine.create у меня уже есть поток в стеке)

EDIT: Im ищет решение, которое использует C API, например. lua_newthread

c++ lua


2 ответа


9 Решение Nicol Bolas [2012-07-08 20:48:00]

Идея довольно проста. Во-первых, вы создаете новый поток.

lua_State *pThread = lua_newthread(L);

Эта функция также толкает этот поток на L. Следующий шаг - получить функцию потока на pThread. Учитывая, что на данный момент у вас есть функция Lua в стеке, следующим шагом будет передача этой функции в стек pThread.

Существует функция, специально предназначенная для передачи значений между потоками: lua_xmove. Однако он переносит только верхние элементы стека. Поэтому вам нужно скопировать функцию Lua из того места, где она находится в стеке L, в начало стека L. Затем lua_xmove в новый стек.

lua_pushvalue(L, #); //Where # is the index in the stack where the function is.
                     //Remember that lua_newthread pushed a value on the stack, so compensate for that.
lua_xmove(L, pThread, 1); //Moves the function to the top of the new stack.

Помните, что lua_xmove перемещает значение, которое удаляет его из L. Итак, lua_pushvalue выталкивает значение, а lua_xmove выдает его. Таким образом, вершина стека снова представляет собой lua_State, представленную pThread.

После этого надавите все параметры, необходимые для отправки функции (которая, по-видимому, равна нулю) и возобновите ее.

lua_resume(pThread, 0);

Общий код:

lua_State *pThread = lua_newthread(L);
lua_pushvalue(L, #); //Where # is the index in the stack where the function is.
                     //Remember that lua_newthread pushed a value on the stack, so compensate for that.
lua_xmove(L, pThread, 1); //Moves the function to the top of the new stack.
lua_resume(pThread, 0);

Нить Lua (созданная в Lua или в C API) - это значение Lua, точно так же, как таблица, userdata, string и т.д. Поэтому она подлежит сборке мусора. Он будет собран, когда Lua обнаружит, что больше нет ссылок на значение.

Помните: lua_newthread толкает поток в исходный стек. Вы можете скопировать его в реестр или в глобальную среду или где бы вы ни планировали, чтобы этот поток постоянно находился. Простое сохранение указателя на lua_State, который он сгенерировал, не гарантирует, что поток останется в живых.


2 jxh [2012-07-08 03:17:00]

Я долго не много делал lua, поэтому я немного ржавый. Но, я думаю, что вы хотите сделать:

  • извлеките luaFunc
  • затем нажмите coroutine.create на
  • затем нажмите luaFunc на
  • и используйте lua_pcall, чтобы получить ваш поток в стеке.

Из ваших комментариев вы хотите использовать lua_newthread. У меня нет опыта с этим, но я нашел этот ответ, который содержит пример программы, которая его использует.