Exposing a type-safe dynamic API with a shared library
===

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 `SetEventHooks`function 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.g`SetHookMouseMove(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`