Exposing a type-safe dynamic API with a shared library - c++

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

As suggested by Kerrek, you can use traits policy to solve your problem. Basically as a part of public API you have to include structures defining callback type for each of your hook id.
// The default traits. If you don't want to have default traits comment body
// of this type out (including curly braces).
template <HookID id>
struct CallbackTraits
{
typedef void (*CallbackType)();
};
// Traits for MouseClick
template <>
struct CallbackTraits<HookID::MouseClick>
{
typedef void (*CallbackType)(int);
};
// Traits for MouseDoubleClick are the same
template <>
struct CallbackTraits<HookID::MouseDoubleClick> : CallbackTraits<HookID::MouseClick> {};
// Traits for MouseMove
template <>
struct CallbackTraits<HookID::MouseMove>
{
typedef void (*CallbackType)(int, int);
};
// actual hooking function
template <HookID id>
void SetEventHook(typename CallbackTraits<id>::CallbackType callback)
{
// do something with id and the callback
}
Now you can use this API following way:
// handlers prototypes
void MouseClicked(int button);
void MouseMoved(int x, int y);
void SomeEvent();
int main()
{
// compiles ok
SetEventHook<HookID::MouseClick>(MouseClicked);
SetEventHook<HookID::MouseMove>(MouseMoved);
// won't compile - function signature incompatible
SetEventHook<HookID::MouseDoubleClick>(MouseMoved);
// will compile if you left default traits body uncommented
SetEventHook<HookID::HookWithNoTraitsDefined>(SomeEvent);
return 0;
}
I've uploaded a working sample here.

Related

Trampolining a non-static C++ member as a registered C callback

I am writing a C++ freeGlut 3.0.0 application. I am having trouble registering a generic callback signature (hopefully a function pointer template argument) with a non static member function that matches the signatures of the declared free-glut callbacks.
To this end, with the help from this answer, I put together a live Coliru working example that demonstrates how to register a C++ non static method as a callback with a C application (in my case the freeGlut library). A better C interface would allow a caller to specify an optional void* user parameter which would typically be bound to this as described here.
FreeGlut does not allow provide a mechanism to do this in their callback registration API, so it seems that I need to use a trampolining technique that I am not very familiar with - especially when it comes to variadic parameter packs and such type_trait magic.
My cobbled together example uses one specific callback signature callback_t. The place where I need help is to allow a more generic callback templated type - perhaps the trampolining example live coliru demo could be adapted to make my example more generic but I am not sure how to get this working. I suspect I need to change the callback_t to somehow allow variadic arguments and a templated return type but I don't know how.
using callback_t = std::add_pointer<int(const char *, int)>::type;
using MyFTWFunction = std::function<void(unsigned char, int, int)>;
template <MyFTWFunction *callback>
class callback_binder {
public:
static void trampoline(unsigned char key, int x, int y) {
return (*callback)(key, x, y);
}
};
// This matches the signature of the callbacks in freeGlut
extern "C" {
// register the keyboard callback here
void glutKeyboardFunc(void(*callback)(unsigned char ch, int x, int y)) {
callback('S', 3, 4);
}
// register Reshape callback here
void glutReshapeFunc(void(*callback)(int, int)) {
callback(1, 2);
}
// register Display callback here
void glutDisplayFunc(void(*callback)(void)) {
callback();
}
}
I need help making it more generic such that I can also register other callbacks.

Calling different template function specialisations based on a run-time value

This is related to a previous question in that it's part of the same system, but it's a different problem.
I'm working on an in-house messaging system, which is designed to send messages (structs) to consumers.
When a project wants to use the messaging system, it will define a set of messages (enum class), the data types (struct), and the relationship between these entities:
template <MessageType E> struct expected_type;
template <> struct expected_type<MessageType::TypeA> { using type = Foo; };
template <> struct expected_type<MessageType::TypeB> { using type = Bar; };
template <> struct expected_type<MessageType::TypeM> { using type = Foo; };
Note that different types of message may use the same data type.
The code for sending these messages is discussed in my previous question. There's a single templated method that can send any message, and maintains type safety using the template definitions above. It works quite nicely.
My question regards the message receiver class. There is a base class, which implements methods like these:
ReceiveMessageTypeA(const Foo & data) { /* Some default action */ };
ReceiveMessageTypeB(const Bar & data) { /* Some default action */ };
ReceiveMessageTypeM(const Foo & data) { /* Some default action */ };
It then implements a single message processing function, like this:
bool ProcessMessage(MessageType msgType, void * data) {
switch (msgType) {
case TypeA:
ReceiveMessageTypeA(data);
break;
case TypeB:
ReceiveMessageTypeB(data);
break;
// Repeat for all supported message types
default:
// error handling
break;
}
}
When a message receiver is required, this base class is extended, and the desired ReceiveMessageTypeX methods are implemented. If that particular receiver doesn't care about a message type, the corresponding function is left unimplemented, and the default from the base class is used instead.
Side note: ignore the fact that I'm passing a void * rather than the specific type. There's some more code in between to handle all that, but it's not a relevant detail.
The problem with the approach is the addition of a new message type. As well as having to define the enum, struct, and expected_type<> specialisation, the base class has to be modified to add a new ReceiveMessageTypeX default method, and the switch statement in the ProcessMessage function must be updated.
I'd like to avoid manually modifying the base class. Specifically, I'd like to use the information stored in expected_type to do the heavy lifting, and to avoid repetition.
Here's my attempted solution:
In the base class, define a method:
template <MessageType msgType>
bool Receive(expected_type<msgType>::type data) {
// Default implementation. Print "Message not supported", or something
}
Then, the subclasses can just implement the specialisations they care about:
template<> Receive<MessageType::TypeA>(const Foo & data) { /* Some processing */ }
// Don't care about TypeB
template<> Receive<MessageType::TypeM>(const Foo & data) { /* Some processing */ }
I think that solves part of the problem; I don't need to define new methods in the base class.
But I can't figure out how to get rid of the switch statement. I'd like to be able to do this:
bool ProcessMessage(MessageType msgType, void * data) {
Receive<msgType>(data);
}
This won't do, of course, because templates don't work like that.
Things I've thought of:
Generating the switch statement from the expected_type structure. I have no idea how to do this.
Maintaining some sort of map of function pointers, and calling the desired one. The problem is that I don't know how to initialise the map without repeating the data from expected_type, which I don't want to do.
Defining expected_type using a macro, and then playing preprocessor games to massage that data into a switch statement as well. This may be viable, but I try to avoid macros if possible.
So, in summary, I'd like to be able to call a different template specialisation based on a run-time value. This seems like a contradiction to me, but I'm hoping someone can point me in a useful direction. Even if that is informing me that this is not a good idea.
I can change expected_type if needed, as long as it doesn't break my Send method (see my other question).
You had right idea with expected_type and Receive templates; there's just one step left to get it all working.
First, we need to give us some means to enumerate over MessageType:
enum class MessageType {
_FIRST = 0,
TypeA = _FIRST,
TypeB,
TypeM = 100,
_LAST
};
And then we can enumerate over MessageType at compile time and generate dispatch functions (using SFINAE to skip values not defined in expected_types):
// this overload works when expected_types has a specialization for this value of E
template<MessageType E> void processMessageHelper(MessageType msgType, void * data, typename expected_type<E>::type*) {
if (msgType == E) Receive<E>(*(expected_type<E>::type*)data);
else processMessageHelper<(MessageType)((int)E + 1)>(msgType, data, nullptr);
}
template<MessageType E> void processMessageHelper(MessageType msgType, void * data, bool) {
processMessageHelper<(MessageType)((int)E + 1)>(msgType, data, nullptr);
}
template<> void processMessageHelper<MessageType::_LAST>(MessageType msgType, void * data, bool) {
std::cout << "Unexpected message type\n";
}
void ProcessMessage(MessageType msgType, void * data) {
processMessageHelper<MessageType::_FIRST>(msgType, data, nullptr);
}
Your title says: "Calling different template function specialisations based on a run-time value"
That can only be done with some sort of manual switch statement, or with virtual functions.
On the one hand, it looks on the surface like you are doing object-oriented programming, but you don't yet have any virtual methods. If you find you are writing pseudo-objects everywhere, but you don't have any virtual functions, then it means you are not doing OOP. This is not a bad thing though. If you overuse OOP, then you might fail to appreciate the particular cases where it is useful and therefore it will just cause more confusion.
Simplify your code, and don't get distracted by OOP
You want the message type object to have some 'magic' associated with it, where it's MessageType controls how it is dispatched. This means you need a virtual function.
struct message {
virtual void Receive() = 0;
}
struct message_type_A : public message {
virtual void Receive() {
....
}
}
This allows you, where appropriate, to pass these objects as message&, and to call msg.process_me()

Linking to dynamically available functions at compile time

Suppose I have the following core class:
class Core {
public:
template<typename T>
void accept(T object);
}
I now want to be able to write methods like this:
void handle(int par);
and register them somewhere during linking/compiling stage and call the correct method registered for some typename in the Core.accept(T) method. For example calling
Core.accept(5) would hand 5 over to the handle(int) function after it is somehow registered. Something like this (not compilable example):
template<typename T>
void Core::accept(T par) {
// constexpr std::map<std::type_info, Function> type_func_mapping;
auto it = type_func_mapping.get(typeid(T)); // Should be constexpr
static_assert (it != type_func_mapping.end(), "No handler found for typename " + typeid(T).name())
auto function = *it; // Also constexpr
function(par);
}
Are there any problems with this approach/does exist a better one?
Note: I want to be able to extract the sources of class Core in a way that I can store them in a read-only header/source file and don't even have to touch them again.
You could use pointer to functions to store the registered function.
static void (*reg_func)(args);
static void register(void (*func)(args)){
reg_func = func;
}
//registration part
register(handle);
//function call inside accept,use can use some sanity checks also
reg_func(5 or whatever)
With this you don't have to touch your core class or even the file containing the core class. You can define the handle function in some other file but take care of visibility mode of handle function. Your handle function will register itself and then accept can call the registered function.

How to pass a Function pointer without exposing class details

I'm creating a library that needs to allow the user to set a callback function.
The interface of this library is as below:
// Viewer Class Interface Exposed to user
/////////////////////////////
#include "dataType_1.h"
#include "dataType_2.h"
class Viewer
{
void SetCallbackFuntion( dataType_1* (Func) (dataType_2* ) );
private:
dataType_1* (*CallbackFunction) (dataType_2* );
}
In a typical usage, the user needs to access an object of dataType_3 within the callback.
However, this object is only known only to his program, like below.
// User usage
#include "Viewer.h"
#include "dataType_3.h"
// Global Declaration needed
dataType_3* objectDataType3;
dataType_1* aFunction( dataType_2* a)
{
// An operation on object of type dataType_3
objectDataType3->DoSomething();
}
main()
{
Viewer* myViewer;
myViewer->SetCallbackFunction( &aFunction );
}
My Question is as follows:
How do I avoid using an ugly global variable for objectDataType3 ?
(objectDataType3 is part of libraryFoo and all the other objects dataType_1, dataType_2 & Viewer are part of libraryFooBar) Hence I would like them to remain as separate as possible.
Don't use C in C++.
Use an interface to represent the fact you want a notification.
If you want objects of type dataType_3 to be notified of an event that happens in the viewer then just make this type implement the interface then you can register the object directly with the viewer for notification.
// The interface
// Very close to your function pointer definition.
class Listener
{
public: virtual dataType_1* notify(dataType_2* param) = 0;
};
// Updated viewer to use the interface defineition rather than a pointer.
// Note: In the old days of C when you registered a callback you normally
// also registered some data that was passed to the callback
// (see pthread_create for example)
class Viewer
{
// Set (or Add) a listener.
void SetNotifier(Listener* l) { listener = l; }
// Now you can just inform all objects that are listening
// directly via the interface. (remember to check for NULL listener)
void NotifyList(dataType_2* data) { if (listener) { listener->notify(data); }
private:
Listener* listener;
};
int main()
{
dataType_3 objectDataType3; // must implement the Listener interface
Viewer viewer;
viewer.SetNotifier(&objectDataType3);
}
Use Boost.Function:
class Viewer
{
void SetCallbackFuntion(boost::function<datatype_1* (dataType_2*)> func);
private:
boost::function<datatype_1* (dataType_2*)> CallbackFunction;
}
Then use Boost.Bind to pass the member function pointer together with your object as the function.
If you don't want or can't use boost, the typical pattern around callback functions like this is that you can pass a "user data" value (mostly declared as void*) when registering the callback. This value is then passed to the callback function.
The usage then looks like this:
dataType_1* aFunction( dataType_2* a, void* user_ptr )
{
// Cast user_ptr to datatype_3
// We know it works because we passed it during set callback
datatype_3* objectDataType3 = reinterpret_cast<datatype_3*>(user_ptr);
// An operation on object of type dataType_3
objectDataType3->DoSomething();
}
main()
{
Viewer* myViewer;
dataType_3 objectDataType3; // No longer needs to be global
myViewer->SetCallbackFunction( &aFunction, &objectDataType3 );
}
The implementation on the other side only requires to save the void* along with the function pointer:
class Viewer
{
void SetCallbackFuntion( dataType_1* (Func) (dataType_2*, void*), void* user_ptr );
private:
dataType_1* (*CallbackFunction) (dataType_2*, void*);
void* user_ptr;
}
boost::/std:: function is the solution here. You can bind member functions to them, and in addition functors and lambdas, if you have a lambda compiler.
struct local {
datatype3* object;
local(datatype3* ptr)
: object(ptr) {}
void operator()() {
object->func();
}
};
boost::function<void()> func;
func = local(object);
func(); // calls object->func() by magic.
Something like this is simple to do:
class Callback
{
public:
virtual operator()()=0;
};
template<class T>
class ClassCallback
{
T* _classPtr;
typedef void(T::*fncb)();
fncb _cbProc;
public:
ClassCallback(T* classPtr,fncb cbProc):_classPtr(classPtr),_cbProc(cbProc){}
virtual operator()(){
_classPtr->*_cbProc();
}
};
Your Viewer class would take a callback, and call it using the easy syntax:
class Viewer
{
void SetCallbackFuntion( Callback* );
void OnCallCallback(){
m_cb->operator()();
}
}
Some other class would register the callback with the viewer by using the ClassCallback template specialization:
// User usage
#include "Viewer.h"
#include "dataType_3.h"
main()
{
Viewer* myViewer;
dataType_3 objectDataType3;
myViewer->SetCallbackFunction( new ClassCallback<dataType_3>(&objectDataType3,&dataType_3::DoSomething));
}
You're asking several questions mixed up in here and this is going to cause you lots of confusion in your answers.
I'm going to focus on your issue with dataType_3.
You state:
I would like to avoid declaring or
including dataType_3 in my library as
it has huge dependencies.
What you need to do is make an interface class for dataType_3 that gives the operations -- the footprint -- of dataType_3 without defining everything in it. You'll find tips on how to do that in this article (among other places). This will allow you to comfortably include a header that gives the footprint for dataType_3 without bringing in all of its dependencies. (If you've got dependencies in the public API you may have to reuse that trick for all of those as well. This can get tedious, but this is the price of having a poorly-designed API.)
Once you've got that, instead of passing in a function for callback consider having your "callback" instead be a class implementing a known interface. There are several advantages to doing this which you can find in the literature, but for your specific example there's a further advantage. You can inherit that interface complete with an instantiated dataType_3 object in the base class. This means that you only have to #include the dataType_3 interface specification and then use the dataType_3 instance provided for you by the "callback" framework.
If you have the option of forcing some form of constraints on Viewer, I would simply template that, i.e.
template <typename CallBackType>
class Viewer
{
public:
void SetCallbackFunctor(CallBackType& callback) { _callee = callback; }
void OnCallback()
{
if (_callee) (*_callee)(...);
}
private:
// I like references, but you can use pointers
boost::optional<CallBackType&> _callee;
};
Then in your dataType_3 implement the operator() to do as needed, to use.
int main(void)
{
dataType_3 objectDataType3;
// IMHO, I would construct with the objectDataType3, rather than separate method
// if you did that, you can hold a direct reference rather than pointer or boost::optional!
Viewer<dataType_3> viewer;
viewer.SetCallbackFunctor(objectDataType3);
}
No need for other interfaces, void* etc.

Dynamic creating of typedef

I'm creating event system. It's based under boost::signals. To make the work easier I'm using typedef for the function signatures.
Everything is okey until I need creating of some new event trought event's system method. I have to create the typedef dynamically on given type to the template function. The problem is the name of typedef.
Some pseudocode I would have:
template<typename EventType>
void create(const string &signalName)
{
typedef EventType signalName;
// ...
}
Is it possible to make such typedef (their names) with some passed string or data or something else? I don't want to make user care about of this.
UPD: So, I have some typedefs list of function signatures - events. I have some templated function for connecting slots, for example. I don't want to force user to input signature by his hands again every time (user is programmer which will use the event system). So I just use my typedefs from special namespace into template argument.
typedefs only matter during compilation. As far as I know it's just an alias for a type.
Template parameters are, by definition, compile time entities. You can not dynamically create template classes on the fly during program execution as far as I am aware.
In this case, I wouldn't go for typedef's. If you want to have several types of events and create them dynamically, you can use a simple class containing the information about the event type. When you have an event, you link it to the event type created before.
Something like this:
class EventType
{
private:
string type;
EventType(string type);
};
class Event
{
private:
string event_name;
EventType *event_type;
Event(string event_name, EventType event_type);
};
...
void create(const string &signalName)
{
EventType *event_type = new EventType("type_x");
Event *event = new Event("event_x", event_type);
}