У меня есть шаблон наблюдателя (или «слушателя»), реализованный в моем коде как таковой:
struct EntityListener
{
public:
virtual void entityModified(Entity& e) = 0;
};
class Entity
{
public:
Entity();
void setListener(EntityListener* listener);
private:
EntityListener* m_listener;
};
Теперь это работает в C ++; класс Entity вызывает entityModified()
метод всякий раз, когда это необходимо. Теперь я хотел бы передать некоторые функциональные возможности Lua, и среди этих функциональных точек есть этот обратный вызов слушателя. Объекты теперь создаются из сценариев Lua. Вопрос в том, как мне достичь функциональности слушателя в Lua?
Например, скрипт Lua в настоящее время делает что-то вроде этого:
function initializeEntity()
-- The entity object is actually created in C++ by the helper
Entity = Helper.createEntity()
-- Here I'd like to hook a Lua function as the Entity's listener
end
Одним из возможных решений является наличие LuaListener
класс в вашем C ++ коде, который содержит «указатель» на функцию Lua и специфичный для Lua setListener
функция, которая вызывается из сценария Lua, который принимает функцию Lua в качестве аргумента и создает LuaListener
экземпляр и передает это фактическому C ++ setListener
,
Таким образом, код Lua будет выглядеть примерно так
function onModified(entity)
-- ...
end
function initializeEntity()
entity = Helper.createEntity()
entity.setListener(onModified)
end
И код C ++ будет выглядеть примерно так (только псевдо-код):
class LuaListener : public EntityListener
{
private:
lua_State* state;
std::string funcName;
public:
void entityModified(Entity& e)
{
// Call function `funcName` in `state`, passing `e` as argument
}
};
class LuaEntity : public Entity
{
public:
void setListenerLua(state, funcName, ...)
{
Entity::setListener(new LuaListener(state, funcName, ...));
}
};