Обработка обратных вызовов событий с помощью Luabind

Я добавляю скрипты с Lua в наше приложение, и мне нужно реализовать привязки для GUI-инструментария. Инструментарий, который мы используем, - это wxWidgets.

Я использую Lua 5.1 и luabind 0.9.1, и до сих пор они работали очень хорошо. Однако я не уверен, как лучше всего обрабатывать события. Например, если вы хотите создать кнопку и печатать строку при ее нажатии, вы пишете что-то подобное на C ++

class MyClass : public wxFrame
{
    MyClass (...)
    {
        b = new wxButton (this, -1, "Click me");
        b->Bind (wxEVT_COMMAND_BUTTON_CLICKED, &MyClass::HandleButtonClick, this);
    }

    void HandleButtonClick (wxCommandEvent& ev)
    {
        wxMessageBox ("You clicked me");
    }
}

API моей мечты для выполнения того же самого в Lua будет выглядеть примерно так:

b = wx.Button (frm, -1, "Click me")
b.on_click = function (ev)
    print ("Button clicked")
end

Или, разрешив несколько обработчиков событий:

b.on_click:add (function (ev)
    print ("Button clicked again ...")
end)

Если это невозможно, то что-то вроде этого, больше напоминающего C ++ API:

b.bind (wx.EVT_COMMAND_BUTTON_CLICKED, function (ev)
    print ("Yet again")
end)

Однако я не уверен, как реализовать это с помощью Luabind без написания класса-оболочки для каждого класса в библиотеке wxWidgets, который я хочу использовать.

Какие-либо предложения?

Может ли Luabind каким-то образом автоматически создавать вспомогательные классы (скажем, wxLuaEventPropagator)? Так что класс wxButton имеет вложенный класс wxLuaEventPropagator для каждого события («on_click» и т. Д.). Еще раз, я не хочу создавать классы-оболочки для каждого класса в wxWidgets, который я использую, поскольку их очень много.

(Да, я знаю о wxLua)


person Jonatan    schedule 06.04.2011    source источник
comment
Вы говорите, что знаете о wxLua - так почему бы не использовать его?   -  person John Zwinck    schedule 10.04.2011
comment
Потому что: 1. wx-часть не будет широко использоваться скриптами, и я думаю, что это довольно тяжелая зависимость (хотя и не обязательно), 2. проект может переместиться на другой инструментарий графического интерфейса в не слишком отдаленном будущем, и большинство важно: 3. Есть другие api, которые мне тоже придется обернуть, так что мне все еще нужно найти решение для этого. Мой текущий план - отказаться от Luabind, хотя он мне очень нравится, и использовать вместо него SWIG.   -  person Jonatan    schedule 11.04.2011
comment
Вы упомянули C ++. Ваше основное приложение написано на C ++?   -  person Jonathan Swinney    schedule 13.05.2011
comment
Я не был знаком с Луабинд. После некоторого исследования я ответил на свой вопрос.   -  person Jonathan Swinney    schedule 13.05.2011
comment
неправильно, Джонатан ... Я думал над этим вопросом и могу ответить на него, если придумываю что-нибудь новое.   -  person Jonathan Swinney    schedule 19.05.2011


Ответы (1)


Для этого вы можете использовать luabind :: object.

Примерный класс: class MyClass {public: void OnMouseMoved (int x, int y); void SetEventFunction (const luabind :: object & fn);

private:
    luabind::object m_eventFunction;
};


void MyClass::SetEventFunction(const luabind::object &fn)
{
    if(luabind::type(fn) == LUA_TFUNCTION)
    {
        cout << "A function" << endl;
        m_eventFunction = fn;
    }
    else
    {
        cout << "Not a function" << endl;
    }
}

void MyClass::OnMouseMoved(int x, int y)
{
    if(m_eventFunction.is_valid())
    {
        luabind::call_function<void>(m_eventFunction, x, y);
    }
}

В коде lua это будет:

myClass = MyClass ()

myClass:SetEventFunction( function (x, y)
    print ("The new mouse position is", x, y)
end)

Чтобы иметь более одной функции для события, вы можете использовать std::vector из luabind::object

person Congelli501    schedule 26.05.2011
comment
Поскольку классы являются частью сторонней библиотеки, мне пришлось бы обернуть каждый класс, используя этот метод. Как я уже говорил выше, сейчас я использую SWIG, так как он позволяет вам легко расширять классы. - person Jonatan; 27.05.2011