Предоставление безопасного динамического API типа -с общей библиотекой

. Я программирую интерфейс API плагина для приложения. Плагины загружаются как общие библиотеки во время выполнения. У них есть доступ к API приложения через интерфейс, например следующий:

class IPluginAPI
{
public:
 virtual bool IsPluginsLoaded(void) = 0;
 virtual bool IsHookingEnabled(void) = 0;
 // And about 50 more methods
};

Плагины могут запрашивать «прослушивание» определенных событий (, таких как MouseClick, MouseScrollи т. д. ). Эти функции составляют более 300 различных событий. Обычно я бы сделал что-то подобное:

extern "C" void SetEventHooks(APITable& table)
{
 table.MouseClick = &PluginMouseClickEvent;
 table.MouseMove = &PluginMouseMoveEvent;
}

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

// Interface IPluginAPI supplies a 'SetEventHook` method such as
void SetEventHook(HookID id, void * callback);

В данном случае HookID— это строго типизированное перечисление, содержащее все идентификаторы функций :

enum class HookID
{
 MouseClick,
 MouseMove,
 //...
};

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

pluginAPI->SetEventHook(ID::MouseClick, &myCallback);

. Проблема с этим подходом заключается в том, что он небезопасен для типов -, и я не могу использовать шаблоны напрямую (, так как это делается во время выполнения в виде библиотек ). Я не хочу выставлять 300 различных функций для каждого события (, например SetHookMouseMove(void (*)(int, int))и так далее ). Моя последняя идея заключается в том, что у плагинов есть функция служебного шаблона, которая делает этот тип безопасным, но я не уверен, как реализовать это простым способом (и без шаблонного кода ):

template <typename T>
SetEventHook(HookID id, T callback)
{
 if(typeof(T) == decltype(/* function type of the ID */))
  gPluginAPI->SetEventHook(id, callback);
 else static_assert("INVALID FUNCTION TYPE");
}

. Итак, проще говоря; как я могу разрешить своим плагинам подключаться к определенным событиям безопасным способом динамического типа -, не раскрывая полную таблицу функций и/или> 300 методов для каждого события?

ПРИМЕЧАНИЕ. :Я использовал указатели на функции для упрощения.но я хочу использоватьstd::function

5
задан Elliott Darfink 18 July 2012 в 19:57
поделиться