Поток управления в Lua

У меня есть проблема, которая, я полагаю, должна быть очень распространенной, и большинство из вас столкнулись бы с ней. Я написал программу на lua, скажем, main.lua, которая при получении ключевого события должна изменять координаты и отображать геометрическую фигуру. Этот код lua вызывает reg.c, где он как бы регистрируется. Теперь в reg.c у меня есть механизм функций, который получает нажатую клавишу и передает ее функции lua, отвечающей за обработку клавиш. Но к тому времени, когда наступает ключевое событие, код lua завершает регистрацию и завершает работу, поэтому вызов из engine() становится незаконным доступом к памяти, что приводит к ошибке сегментации.

Также я полагаю, что у нас не может быть зависания вызова lua в функции reg и вызова функции движка откуда-то еще.

Тогда какое должно быть решение, пожалуйста, проведите меня через это.


@jacob: вот прототип того, чего я пытаюсь достичь:

function key_handler() //this function will get the latest key pressed from some other function
{
     draw.image();
     draw.geometry();
     ...
     ...

     while(1)
     {
         //draw Points until some condition goes wrong      
     }

}

Теперь, после входа в key_handler, пока он занят рисованием точек, если и до тех пор, пока не возникнет условие отказа, я не могу получить нажатую клавишу до этого времени.

Я надеюсь, что это объяснение намного проще и донесло мою точку зрения, а также поможет другим понять проблему. Мне очень жаль, но я не умею выражать или заставлять других понимать.

Еще одна вещь, которую я объяснил синтаксисом C, однако это полностью реализовано в lua.


person ashutosh    schedule 25.06.2012    source источник
comment
Трудно понять вашу настройку и то, чего вы пытаетесь достичь из своего вопроса (например, никто не знает, что делает или должен делать reg.c, то же самое для engine()). Пожалуйста, уточните и дайте минимальный пример кода, чтобы продемонстрировать, что не работает.   -  person jpjacobs    schedule 27.06.2012
comment
@jpjacobs: я обновил проблему в меру своих усилий, пожалуйста, посмотрите, можете ли вы порекомендовать мне какое-нибудь решение проблемы.   -  person ashutosh    schedule 03.07.2012
comment
Я пробовал использовать сопрограммы, но это не помогло   -  person ashutosh    schedule 03.07.2012
comment
@jpjacobs Я обновил проблему в меру своих усилий, пожалуйста, посмотрите, можете ли вы порекомендовать мне какое-то решение проблемы.   -  person ashutosh    schedule 04.07.2012


Ответы (1)


Ваш фрагмент кода по-прежнему в значительной степени неинформативен (в идеале нужно просто запустить ваш код в стандартном интерпретаторе Lua и увидеть вашу проблему). Если вы описываете проблему Lua, используйте код Lua для ее описания.

Однако я начинаю видеть, куда вы хотите пойти.

То, что вам нужно сделать, это иметь сопрограмму, которая вызывается в вашем обработчике ключей, которая передает аргумент обратно вашему обработчику:

function isContinue() --just to simulate whatever function you use getting keypresses.
-- in whatever framework you're using there will probably be a function key_pressed or the like.
    print('Initialize checking function')
    while true do
        print('Continue looping?')
        local ans = io.read():match('[yY]')
        local action
        if not ans then
            print('Do what instead?')
            action = io.read()
            if action:match('kill') then -- abort keychecker.
                break
            end
        end
        coroutine.yield(ans,action)
    end
    print('finalizing isContinue')
    return nil,'STOP' -- important to tell key_handler to quit too, else it'll be calling a dead coroutine.
end

function key_handler()
    local coro = coroutine.create(isContinue)
    local stat,cont,action
    while true do
        print'Draw point'
        stat,cont,action = coroutine.resume(coro)
        if not stat then
            print('Coroutine errored:',cont)
        elseif not cont then
            print('isContinue interrupted keyhandler')
            print("We'll "..action.." instead.")
            break
        end
    end
    print('finalizing key_handler')
end

key_handler()
-- type something containing y or Y to continue, all else aborts.
-- when aborting, you get asked what to do instead of continuing, 
--- with "kill" being a special case.

Это должно быть понятно. Возможно, вам стоит внимательно изучить Программирование на Lua, глава 9: Сопрограммы.

Большая трудность (ну, если вы не привыкли к совместной работе с потоками) заключается в том, что сопрограмма должна уступать сама себя: не вызывающая функция отвечает за возврат управления.

Надеюсь, это поможет вам.

person jpjacobs    schedule 04.07.2012