Эквивалент 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
. У меня нет опыта с этим, но я нашел этот ответ, который содержит пример программы, которая его использует.