I'm programming a plugin API interface for an application. The plugins are loaded as shared libraries at run time. They have access to the application API through an interface, such as the following:
class IPluginAPI { public: virtual bool IsPluginsLoaded(void) = 0; virtual bool IsHookingEnabled(void) = 0; // And about 50 more methods }; Plugins can request to 'listen' on certain events (such as MouseClick, MouseScroll etc.). These functions make up a total of >300 different events. Normally I would have done something like this:
extern "C" void SetEventHooks(APITable& table) { table.MouseClick = &PluginMouseClickEvent; table.MouseMove = &PluginMouseMoveEvent; } Whereas the SetEventHooksfunction resides within the plugin library and is called from the application, and the plugins can listen to functions of interest by pointing to their functions. This is not the method I want to use, but I want to offer some kind of abstraction instead. This is what I had in mind:
// Interface IPluginAPI supplies a 'SetEventHook` method such as void SetEventHook(HookID id, void * callback); In this case HookID is a strong typed enum which contains all function IDs:
enum class HookID { MouseClick, MouseMove, // ... }; So the plugin would use this function to listen to events:
pluginAPI->SetEventHook(ID::MouseClick, &myCallback); The problem with this approach is that it is not type-safe and I cannot use templates directly (since this is done at runtime as libraries). I don't want to expose 300 different functions either for each event (e.gSetHookMouseMove(void (*)(int, int)) and so on). My last idea, is that the plugins have a utility template function which makes this type safe, but I'm not sure how to implement this in a simple way (and without boilerplate code):
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"); } So to put it simple; how can I enable my plugins to hook to certain events in a dynamic type-safe way without exposing a complete function table and/or >300 methods for each event?
NOTE: I used function pointers for simplification, but I want to use std::function
dynamic_cast, and everything is good.Tsupposed to be? You know that function pointers and object pointers are not in general compatible?template <HookID ID> void SetEventHook(typename CallbackType<ID>::type callback);?