Using functors/lambdas with C callbacks - c++

I'm in the process of writing a C++11 wrapper for a popular open-source C library, providing RAII and all the other niceties you'd expect. The wrapper will be header-only (so one only needs to link to the original C lib), and in addition one of the principles I would like to stick to is that the wrapper should be "zero overhead" as far as possible, that is, when optimisation is enabled everything should be inlined so that only the C function calls remain.
For the most part, this isn't all that difficult: I have classes which hold pointers to the (opaque) C types, with constructors which call "create" functions, destructors which call "destroy" functions, methods which call C functions etc etc, just as you'd expect. So far, so easy.
However, one of the problems I'm having is how to deal with callbacks. The library has several entry points of the form
typedef <function signature> CallbackType;
void set_callback(CallbackType cb, void* data);
such that the underlying C library stores cb and data in static variables, and when particular events occur, the callback is fired and data is passed back to it along with other arguments.
I'd like to provide wrappers so that any C++ callable (i.e. functions, functors, lambdas, method calls using std::bind etc) can be used in a callback. However, functors and (capturing) lambdas are objects which need to be stored somewhere in order to ensure that they're still valid when the callback is fired. And exactly where to store them seems problematic... I can't put them on the heap as they then can't be deleted, and I can't (easily) use static variables because of the header-only nature of my library.
Does anyone have any advice/ingenious ideas/hacks that can be used in a situation like this?
Thanks in advance.
To n.m., if you see this: apologies for the mix-up the other day, I got busted posting this question about a personal project on work time so thought it best to delete it, it only had 5 views at the time so I thought I got away with it but obviously not. I'd be interested in your answer if you don't mind typing it again?

Place subscription handle and callback object in the single subscription wrapper. Then it's users responsibility to retain this wrapper as long as he wants to get callbacks from your c-library.
class subscription
{
std::function<void(int)> m_f;
static void callback(int param, void* data)
{
static_cast<subscription*>(data)->m_f( param );
}
subscription( const subscription& other ) = delete;
subscription& operator=( const subscription& ) = delete;
public:
subscription( const std::function<void(int)>& f ) : m_f(f)
{
set_callback( &callback, this);
}
~subscription()
{
clear_callback(&callback, this);
}
};
Usage:
subscription s( [](int param){ std::cout<<param*2<<std::endl; } );

Related

GetFunctionPointerForDelegate callback only works once

I'm having trouble with unmanaged-to-managed callback in C++/CLI. It works exactly one time and then silently fails
My managed Device class holds an unmanaged object (GsDevice) from a separate DLL. It gives the unamanaged object a callback function set up via interop. GsDevice needs to asynchronously notify Device when things change.
The callback was silently failing every time. The debugger was stepping right over it (even in dissasembly. Then I tried to make GsDevice invoke the callback it as the moment it received it. THEN it works. Just the one time.
I assume something is being moved or garbage-collected out from under me but I cannot determine what or why. Can anyone spot what I am doing wrong?
Below is the unmanaged GsDevice class. It lives in a separate, unmanaged DLL. I've left out most of it except for the subscription mechanism that the managed client uses and the notify mechanism by which the this class calls back to the managed one.
The .H file
struct GsDeviceMembers;
class GsDevice : public std::enable_shared_from_this<GsDevice>
{
GsDeviceMembers* m_p; // PIMPL idiom
public:
typedef void (__stdcall *PROPCHANGECALLBACK)(GsDevice*, const std::string&);
void GsDeviceDllExport setPropertyChangedCallback(PROPCHANGECALLBACK cb);
protected:
void raisePropertyChanged(const std::string& prop);
}
And the .CPP file
void GsDevice::setPropertyChangedCallback(PROPCHANGECALLBACK cb)
{
std::unique_lock<std::mutex> lk (m_d->mtxClients);
cb(this, std::string("joe")); // TEST: Call callback right away to ensure it's good.
m_p->cb = cb; // Save off the one client's callback
}
void GsDevice::raisePropertyChanged(const std::string& prop)
{
std::unique_lock<std::mutex> lk (m_d->mtxClients);
m_p->cb(this, prop); // Invoke callback: THIS NEVER WORKS*****
}
Below is the managed client Device class that tries to receive callbacks from the unmanaged GsDevice.
The .H file
struct DeviceUnmanagedMembers; for PIMPL idiom storing unmanaged members.
public ref class Device : public INotifyPropertyChanged
{
public:
virtual event PropertyChangedEventHandler^ PropertyChanged;
private:
DeviceUnmanagedMembers* m_p; // PIMPL idiom
GCHandle m_callbackHandle; // Keeps callback locked into one memory address
protected:
Device(std::shared_ptr<GsDevice> dev);
delegate void PropertyChangedDelegate(GsDevice* sender, const std::string& propName);
virtual void OnPropertyChanged(Gs:Device* pSender, const std::string& propName);
private:
// I am saving off these as member variables in case it helps .NET keep things
// alive. So far, that's not working.
PropertyChangedDelegate^ m_dg;
System::IntPtr^ m_ptr;
};
The .CPP file
struct DeviceUnmanagedMembers
{
std::shared_ptr<GsDevice> spDevice;
DeviceUnmanagedMembers(std::shared_ptr<GsDevice> dev) : spDevice(dev) { }
};
Device::Device(std::shared_ptr<GsDevice> dev) : m_p(new DeviceUnmanagedMembers(dev))
{
// Get a delegate for our callback function and lock it into memory
auto pcDelegate = gcnew PropertyChangedDelegate(this, &Device::OnPropertyChanged);
m_callbackHandle = GCHandle::Alloc(pcDelegate);
auto callback = Marshal::GetFunctionPointerForDelegate(pcDelegate);
auto ptrInt = callback.ToPointer();
auto ptrFun = static_cast<GsDevice::PROPCHANGECALLBACK>(ptrInt);
// Now hook up to the unamanged client for a callback. This actually immediately
// calls me back (to OnPropertyChanged) but all subsequent attempts by the
// unmanaged object to call me back do nothing.
dev->setPropertyChangedCallback(ptrFun);
// Save off these items just in case it helps (It doesn't)
m_dg = pcDelegate;
m_ptr = callback;
}
void Device::OnPropertyChanged(GsDevice* sender, const std::string& propName)
{
// This is the function the unmanaged client is trying to call back. It works
// the very first time the client does it but never after.
RaisePropertyChanged(propName);
}
Notes:
Neither Device nor GsDevice object is being cleaned up. They both still exist because I continue to invoke them with function calls from managed to unmanaged code.
The unmanaged device keeps trying and failing to call the callback. No error. No exception. It just steps over the call.
I've compared the exact pointer values of the callback from the first time (when it works) and all subsequent times when it fails. Its exactly the same.
The C++/CLI assembly is built with .NET 5.0 and Visual Studio 2019
The unmanaged C++ code is built with C++17 features enabled (if that matters)
You appear to be doing the right things to prevent the garbage collector from tossing out the unmanaged trampoline generated by GetFunctionPointerForDelegate. (In Fact, either one of GCHandle.Alloc or keeping a member variable pointing to the delegate instance should be sufficient, you gain no benefit from doing both). This is a common trap for use of GetFunctionPointerForDelegate but it is not your problem.
The other thing I noticed is that you haven't made your delegate suitable for use with GetFunctionPointerForDelegate. Really, .NET just ought to throw an exception if you use GetFunctionPointerForDelegate on a delegate type that doesn't have the UnmanagedFunctionPointerAttribute applied to it.
Add that attribute to delegate void PropertyChangedDelegate(GsDevice* sender, const std::string& propName);, set the correct calling convention (and maybe other things), and try again.
Beyond that, your function type really is not .NET-friendly at all. GetFunctionPointerForDelegate does not expect to work with types like const std::string&.
Does the unmanaged API not provide some user context pointer where you can store a GCHandle to your managed object? If it does, then make an ordinary non-member function to pass as the callback (which you can now create with just &name_of_function -- no delegate, no GetFunctionPointerForDelegate) and in that function, retrieve the pointer, re-hydrate the GCHandle, find your managed object, convert the other argument to a System::String^ and call the .NET member function.
I am posting my own answer because while Ben's suggestions were excellent, the cause appears to have been something different: My liberal use of header-only, unmanaged classes in C++/CLI managed code. I've slowly come to realize that C++/CLI assemblies can become confused by this.
I unexpectedly saw my problems fixed merely by moving unmanaged code from header files to their own .CPP files (with attendant #pragma unmanaged statements for good measure). I was able to leave all my Interop code just as it was. No gcroots or data-type changes needed.
My best guess is that header-only code causes the compiler to fail to generate all of the necessary unmanaged-to-managed transitions in some places and that without such transitions, callbacks just don't work.
This was all complicated by having the added effect of making the debugger simply ignore breakpoints even when the code executed -- but only sometimes. I would repeatedly see a breakpoint on a log statement get hit far fewer times than the statement itself dumped. Again, all this seems to have been fixed merely by separating .CPP and .H unmanaged code.

Dynamic Libraries, plugin frameworks, and function pointer casting in c++

I am trying to create a very open plugin framework in c++, and it seems to me that I have come up with a way to do so, but a nagging thought keeps telling me that there is something very, very wrong with what I am doing, and it either won't work or it will cause problems.
The design I have for my framework consists of a Kernel that calls each plugin's init function. The init function then turns around and uses the Kernel's registerPlugin and registerFunction to get a unique id and then register each function the plugin wants to be accessible using that id, respectively.
The function registerPlugin returns the unique id. The function registerFunction takes that id, the function name, and a generic function pointer, like so:
bool registerFunction(int plugin_id, string function_name, plugin_function func){}
where plugin_function is
typedef void (*plugin_function)();
The kernel then takes the function pointer and puts it in a map with the function_name and plugin_id. All plugins registering their function must caste the function to type plugin_function.
In order to retrieve the function, a different plugin calls the Kernel's
plugin_function getFunction(string plugin_name, string function_name);
Then that plugin must cast the plugin_function to its original type so it can be used. It knows (in theory) what the correct type is by having access to a .h file outlining all the functions the plugin makes available. Plugins, by the by, are implemented as dynamic libraries.
Is this a smart way to accomplish the task of allowing different plugins to connect with each other? Or is this a crazy and really terrible programming technique? If it s, please point me in the direction of the correct way to accomplish this.
EDIT: If any clarification is needed, ask and it will be provided.
Function pointers are strange creatures. They're not necessarily the same size as data pointers, and hence cannot be safely cast to void* and back. But, the C++ (and C) specifications allow any function pointer to be safely cast to another function pointer type (though you have to later cast it back to the earlier type before calling it if you want defined behaviour). This is akin to the ability to safely cast any data pointer to void* and back.
Pointers to methods are where it gets really hairy: a method pointer might be larger than a normal function pointer, depending on the compiler, whether the application is 32- or 64-bit, etc. But even more interesting is that, even on the same compiler/platform, not all method pointers are the same size: Method pointers to virtual functions may be bigger than normal method pointers; if multiple inheritance (with e.g. virtual inheritance in the diamond pattern) is involved, the method pointers can be even bigger. This varies with compiler and platform too. This is also the reason that it's difficult to create function objects (that wrap arbitrary methods as well as free functions) especially without allocating memory on the heap (it's just possible using template sorcery).
So, by using function pointers in your interface, it becomes unpractical for the plugin authors to pass back method pointers to your framework, even if they're using the same compiler. This might be an acceptable constraint; more on this later.
Since there's no guarantee that function pointers will be the same size from one compiler to the next, by registering function pointers you're limiting the plugin authors to compilers that implement function pointers having the same size as your compiler does. This wouldn't necessarily be so bad in practice, since function pointer sizes tend to be stable across compiler versions (and may even be the same for multiple compilers).
The real problems start to arise when you want to call the functions pointed to by the function pointers; you can't safely call the function at all if you don't know its true signature (you will get poor results ranging from "not working" to segmentation faults). So, the plugin authors would be further limited to registering only void functions that take no parameters.
It gets worse: the way a function call actually works at the assembler level depends on more than just the signature and function pointer size. There's also the calling convention, the way exceptions are handled (the stack needs to be properly unwound when an exception is thrown), and the actual interpretation of the bytes of function pointer (if it's larger than a data pointer, what do the extra bytes signify? In what order?). At this point, the plugin author is pretty much limited to using the same compiler (and version!) that you are, and needs to be careful to match the calling convention and exception handling options (with the MSVC++ compiler, for example, exception handling is only explicitly enabled with the /EHsc option), as well as use only normal function pointers with the exact signature you define.
All the restrictions so far can be considered reasonable, if a bit limiting. But we're not done yet.
If you throw in std::string (or almost any part of the STL), things get even worse though, because even with the same compiler (and version), there are several different flags/macros that control the STL; these flags can affect the size and meaning of the bytes representing string objects. It is, in effect, like having two different struct declarations in separate files, each with the same name, and hoping they'll be interchangeable; obviously, this doesn't work. An example flag is _HAS_ITERATOR_DEBUGGING. Note that these options can even change between debug and release mode! These types of errors don't always manifest themselves immediately/consistently and can be very difficult to track down.
You also have to be very careful with dynamic memory management across modules, since new in one project may be defined differently from new in another project (e.g. it may be overloaded). When deleting, you might have a pointer to an interface with a virtual destructor, meaning the vtable is needed to properly delete the object, and different compilers all implement the vtable stuff differently. In general, you want the module that allocates an object to be the one to deallocate it; more specifically, you want the code that deallocates an object to have been compiled under the exact same conditions as the code that allocated it. This is one reason std::shared_ptr can take a "deleter" argument when it is constructed -- because even with the same compiler and flags (the only guaranteed safe way to share shared_ptrs between modules), new and delete may not be the same everywhere the shared_ptr can get destroyed. With the deleter, the code that creates the shared pointer controls how it is eventually destroyed too. (I just threw this paragraph in for good measure; you don't seem to be sharing objects across module boundaries.)
All of this is a consequence of C++ having no standard binary interface (ABI); it's a free-for-all, where it is very easy to shoot yourself in the foot (sometimes without realising it).
So, is there any hope? You betcha! You can expose a C API to your plugins instead, and have your plugins also expose a C API. This is quite nice because a C API can be interoperated with from virtually any language. You don't have to worry about exceptions, apart from making sure they can't bubble up above the plugin functions (that's the authors' concern), and it's stable no matter the compiler/options (assuming you don't pass STL containers and the like). There's only one standard calling convention (cdecl), which is the default for functions declared extern "C". void*, in practice, will be the same across all compilers on the same platform (e.g. 8 bytes on x64).
You (and the plugin authors) can still write your code in C++, as long as all the external communication between the two uses a C API (i.e. pretends to be a C module for the purposes of interop).
C function pointers are also likely compatible between compilers in practice, though if you'd rather not depend on this you could have the plugin register a function name (const char*) instead of address, and then you could extract the address yourself using, e.g., LoadLibrary with GetProcAddress for Windows (similarly, Linux and Mac OS X have dlopen and dlsym). This works because name-mangling is disabled for functions declared with extern "C".
Note that there's no direct way around restricting the registered functions to be of a single prototype type (otherwise, as I've said, you can't call them properly). If you need to give a particular parameter to a plugin function (or get a value back), you'll need to register and call the different functions with different prototypes separately (though you could collapse all the function pointers down to a common function pointer type internally, and only cast back at the last minute).
Finally, while you cannot directly support method pointers (which don't even exist in a C API, but are of variable size even with a C++ API and thus cannot be easily stored), you can allow the plugins to supply a "user-data" opaque pointer when registering their function, which is passed to the function whenever it's called; this gives the plugin authors an easy way to write function wrappers around methods and store the object to apply the method to in the user-data parameter. The user-data parameter can also be used for anything else the plugin author wants, which makes your plugin system much easier to interface with and extend. Another example use is to adapt between different function prototypes using a wrapper and extra arguments stored in the user-data.
These suggestions lead to code something like this (for Windows -- the code is very similar for other platforms):
// Shared header
extern "C" {
typedef void (*plugin_function)(void*);
bool registerFunction(int plugin_id, const char* function_name, void* user_data);
}
// Your plugin registration code
hModule = LoadLibrary(pluginDLLPath);
// Your plugin function registration code
auto pluginFunc = (plugin_function)GetProcAddress(hModule, function_name);
// Store pluginFunc and user_data in a map keyed to function_name
// Calling a plugin function
pluginFunc(user_data);
// Declaring a plugin function
extern "C" void aPluginFunction(void*);
class Foo { void doSomething() { } };
// Defining a plugin function
void aPluginFunction(void* user_data)
{
static_cast<Foo*>(user_data)->doSomething();
}
Sorry for the length of this reply; most of it can be summed up with "the C++ standard doesn't extend to interoperation; use C instead since it at least has de facto standards."
Note: Sometimes it's simplest just to design a normal C++ API (with function pointers or interfaces or whatever you like best) under the assumption that the plugins will be compiled under exactly the same circumstances; this is reasonable if you expect all the plugins to be developed by yourself (i.e. the DLLs are part of the project core). This could also work if your project is open-source, in which case everybody can independently choose a cohesive environment under which the project and the plugins are compiled -- but then this makes it hard to distribute plugins except as source code.
Update: As pointed out by ern0 in the comments, it's possible to abstract the details of the module interoperation (via a C API) so that both the main project and the plugins deal with a simpler C++ API. What follows is an outline of such an implementation:
// iplugin.h -- shared between the project and all the plugins
class IPlugin {
public:
virtual void register() { }
virtual void initialize() = 0;
// Your application-specific functionality here:
virtual void onCheeseburgerEatenEvent() { }
};
// C API:
extern "C" {
// Returns the number of plugins in this module
int getPluginCount();
// Called to register the nth plugin of this module.
// A user-data pointer is expected in return (may be null).
void* registerPlugin(int pluginIndex);
// Called to initialize the nth plugin of this module
void initializePlugin(int pluginIndex, void* userData);
void onCheeseBurgerEatenEvent(int pluginIndex, void* userData);
}
// pluginimplementation.h -- plugin authors inherit from this abstract base class
#include "iplugin.h"
class PluginImplementation {
public:
PluginImplementation();
};
// pluginimplementation.cpp -- implements C API of plugin too
#include <vector>
struct LocalPluginRegistry {
static std::vector<PluginImplementation*> plugins;
};
PluginImplementation::PluginImplementation() {
LocalPluginRegistry::plugins.push_back(this);
}
extern "C" {
int getPluginCount() {
return static_cast<int>(LocalPluginRegistry::plugins.size());
}
void* registerPlugin(int pluginIndex) {
auto plugin = LocalPluginRegistry::plugins[pluginIndex];
plugin->register();
return (void*)plugin;
}
void initializePlugin(int pluginIndex, void* userData) {
auto plugin = static_cast<PluginImplementation*>(userData);
plugin->initialize();
}
void onCheeseBurgerEatenEvent(int pluginIndex, void* userData) {
auto plugin = static_cast<PluginImplementation*>(userData);
plugin->onCheeseBurgerEatenEvent();
}
}
// To declare a plugin in the DLL, just make a static instance:
class SomePlugin : public PluginImplementation {
virtual void initialize() { }
};
SomePlugin plugin; // Will be created when the DLL is first loaded by a process
// plugin.h -- part of the main project source only
#include "iplugin.h"
#include <string>
#include <vector>
#include <windows.h>
class PluginRegistry;
class Plugin : public IPlugin {
public:
Plugin(PluginRegistry* registry, int index, int moduleIndex)
: registry(registry), index(index), moduleIndex(moduleIndex)
{
}
virtual void register();
virtual void initialize();
virtual void onCheeseBurgerEatenEvent();
private:
PluginRegistry* registry;
int index;
int moduleIndex;
void* userData;
};
class PluginRegistry {
public:
registerPluginsInModule(std::string const& modulePath);
~PluginRegistry();
public:
std::vector<Plugin*> plugins;
private:
extern "C" {
typedef int (*getPluginCountFunc)();
typedef void* (*registerPluginFunc)(int);
typedef void (*initializePluginFunc)(int, void*);
typedef void (*onCheeseBurgerEatenEventFunc)(int, void*);
}
struct Module {
getPluginCountFunc getPluginCount;
registerPluginFunc registerPlugin;
initializePluginFunc initializePlugin;
onCheeseBurgerEatenEventFunc onCheeseBurgerEatenEvent;
HMODULE handle;
};
friend class Plugin;
std::vector<Module> registeredModules;
}
// plugin.cpp
void Plugin::register() {
auto func = registry->registeredModules[moduleIndex].registerPlugin;
userData = func(index);
}
void Plugin::initialize() {
auto func = registry->registeredModules[moduleIndex].initializePlugin;
func(index, userData);
}
void Plugin::onCheeseBurgerEatenEvent() {
auto func = registry->registeredModules[moduleIndex].onCheeseBurgerEatenEvent;
func(index, userData);
}
PluginRegistry::registerPluginsInModule(std::string const& modulePath) {
// For Windows:
HMODULE handle = LoadLibrary(modulePath.c_str());
Module module;
module.handle = handle;
module.getPluginCount = (getPluginCountFunc)GetProcAddr(handle, "getPluginCount");
module.registerPlugin = (registerPluginFunc)GetProcAddr(handle, "registerPlugin");
module.initializePlugin = (initializePluginFunc)GetProcAddr(handle, "initializePlugin");
module.onCheeseBurgerEatenEvent = (onCheeseBurgerEatenEventFunc)GetProcAddr(handle, "onCheeseBurgerEatenEvent");
int moduleIndex = registeredModules.size();
registeredModules.push_back(module);
int pluginCount = module.getPluginCount();
for (int i = 0; i < pluginCount; ++i) {
auto plugin = new Plugin(this, i, moduleIndex);
plugins.push_back(plugin);
}
}
PluginRegistry::~PluginRegistry() {
for (auto it = plugins.begin(); it != plugins.end(); ++it) {
delete *it;
}
for (auto it = registeredModules.begin(); it != registeredModules.end(); ++it) {
FreeLibrary(it->handle);
}
}
// When discovering plugins (e.g. by loading all DLLs in a "plugins" folder):
PluginRegistry registry;
registry.registerPluginsInModule("plugins/cheeseburgerwatcher.dll");
for (auto it = registry.plugins.begin(); it != registry.plugins.end(); ++it) {
(*it)->register();
}
for (auto it = registry.plugins.begin(); it != registry.plugins.end(); ++it) {
(*it)->initialize();
}
// And then, when a cheeseburger is actually eaten:
for (auto it = registry.plugins.begin(); it != registry.plugins.end(); ++it) {
auto plugin = *it;
plugin->onCheeseBurgerEatenEvent();
}
This has the benefit of using a C API for compatibility, but also offering a higher level of abstraction for plugins written in C++ (and for the main project code, which is C++). Note that it lets multiple plugins be defined in a single DLL. You could also eliminate some of the duplication of function names by using macros, but I chose not to for this simple example.
All of this, by the way, assumes plugins that have no interdependencies -- if plugin A affects (or is required by) plugin B, you need to devise a safe method for injecting/constructing dependencies as needed, since there's no way of guaranteeing what order the plugins will be loaded in (or initialized). A two-step process would work well in that case: Load and register all plugins; during registration of each plugin, let them register any services they provide. During initialization, construct requested services as needed by looking at the registered service table. This ensures that all services offered by all plugins are registered before any of them are attempted to be used, no matter what order plugins get registered or initialized in.
The approach you took is sane in general, but I see a few possible improvements.
Your kernel should export C functions with a conventional calling convention (cdecl, or maybe stdcall if you are on Windows) for the registration of plugins and functions. If you use a C++ function then you are forcing all plugin authors to use the same compiler and compiler version that you use, since many things like C++ function name mangling, STL implementation and calling conventions are compiler specific.
Plugins should only export C functions like the kernel.
From the definition of getFunction it seems each plugin has a name, which other plugins can use to obtain its functions. This is not a safe practice, two developers can create two different plugins with the same name, so when a plugin asks for some other plugin by name it may get a different plugin than the expected one. A better solution would be for plugins to have a public GUID. This GUID can appear in each plugin's header file, so that other plugins can refer to it.
You have not implemented versioning. Ideally you want your kernel to be versioned because invariably you will change it in the future. When a plugin registers with the kernel it passes the version of the kernel API it was compiled against. The kernel then can decide if the plugin can be loaded. For example, if kernel version 1 receives a registration request for a plugin that requires kernel version 2 you have a problem, the best way to address that is to not allow the plugin to load since it may need kernel features that are not present in the older version. The reverse case is also possible, kernel v2 may or may not want to load plugins that were created for kernel v1, and if it does allow it it may need to adapt itself to the older API.
I'm not sure I like the idea of a plugin being able to locate another plugin and call its functions directly, as this breaks encapsulation. It seems better to me if plugins advertise their capabilities to the kernel, so that other plugins can find services they need by capability instead of by addressing other plugins by name or GUID.
Be aware that any plugin that allocates memory needs to provide a deallocation function for that memory. Each plugin could be using a different run-time library, so memory allocated by a plugin may be unknown to other plugins or the kernel. Having allocation and deallocation in the same module avoids problems.
C++ has no ABI. So what you want doing has a restriction: the plugins and your framework must compile & link by same compiler & linker with same parameter in same os. That is meaningless if the achievement is inter-operation in form of binary distribution because each plugin developed for framework has to prepare many version which target at different compiler on different os. So distrbute source code will be more practical than this and that's the way of GNU(download a src, configure and make)
COM is a chose, but it is too complex and out-of-date. Or managed C++ on .Net runtime. But they are only on ms os. If you want a universal solution, I suggest you change to another language.
As jean mentions, since there is no standard C++ ABI and standard name mangling conventions you are stuck to compile things with same compiler and linker. If you want a shared library/dll kind of plugins you have to use something C-ish.
If all will be compiled with same compiler and linker, you may want to also consider std::function.
typedef std::function<void ()> plugin_function;
std::map<std::string, plugin_function> fncMap;
void register_func(std::string name, plugin_function fnc)
{
fncMap[name] = fnc;
}
void call(std::string name)
{
auto it = fncMap.find(name);
if (it != fncMap.end())
(it->second)(); // it->second is a function object
}
///////////////
void func()
{
std::cout << "plain" << std::endl;
}
class T
{
public:
void method()
{
std::cout << "method" << std::endl;
}
void method2(int i)
{
std::cout << "method2 : " << i << std::endl;
}
};
T t; // of course "t" needs to outlive the map, you could just as well use shared_ptr
register_func("plain", func);
register_func("method", std::bind(&T::method, &t));
register_func("method2_5", std::bind(&T::method2, &t, 5));
register_func("method2_15", std::bind(&T::method2, &t, 15));
call("plain");
call("method");
call("method2_5");
call("method2_15");
You can also have plugin functions that take argumens. This will use the placeholders for std::bind, but soon you can find that it is somewhat lacking behind boost::bind. Boost bind has nice documentation and examples.
There is no reason why you should not do this. In C++ using this style of pointer is the best since it's just a plain pointer. I know of no popular compiler that would do anything as brain-dead as not making a function pointer like a normal pointer. It is beyond the bounds of reason that someone would do something so horrible.
The Vst plugin standard operates in a similar way. It just uses function pointers in the .dll and does not have ways of calling directly to classes. Vst is a very popular standard and on windows people use just about any compiler to do Vst plugins, including Delphi which is pascal based and has nothing to do with C++.
So I would do exactly what you suggest personally. For the common well-known plugins I would not use a string name but an integer index which can be looked up much faster.
The alternative is to use interfaces but I see no reason to if your thinking is already based around function pointers.
If you use interfaces then it is not so easy to call the functions from other languages. You can do it from Delphi but what about .NET.
With your function pointer style suggestion you can use .NET to make one of the plugins for example. Obviously you would need to host Mono in your program to load it but just for hypothetical purposes it illustrates the simplicity of it.
Besides, when you use interfaces you have to get into reference counting which is nasty. Stick your logic in function pointers like you suggest and then wrap the control in some C++ classes to do the calling and stuff for you. Then other people can make the plugins with other languages such as Delphi Pascal, Free Pascal, C, Other C++ compilers etc...
But as always, regardless of what you do, exception handling between compilers will remain an issue so you have to think about the error handling. Best way is that the plugins own method catches own plugin exceptions and returns an error code to the kernel etc...
With all the excellent answers above, I'll just add that this practice is actually pretty wide distributed. In my practice, I've seen it both in commercial projects and in freeware/opensource ones.
So - yes, it's good and proven architecture.
You don't need to register functions manually. Really? Really.
What you could use is a proxy implementation for your plugin interface, where each function loads its original from the shared library on demand, transparently, and calls it. Whoever reaches a proxy object of that interface definition just can call the functions. They will be loaded on demand.
If plugins are singletons, then there is no need for manual binding at all (otherwise the correct instance has to be chosen first).
The idea for the developer of a new plugin would be to describe the interface first, then have a generator which generates a stub for the implementation for the shared library, and additionally a plugin proxy class with the same signature but with the autoloading on demand which then is used in the client software. Both should fulfill the same interface (in C++ a pure abstract class).

Serializing function objects

Is it possible to serialize and deserialize a std::function, a function object, or a closure in general in C++? How? Does C++11 facilitate this? Is there any library support available for such a task (e.g., in Boost)?
For example, suppose a C++ program has a std::function which is needed to be communicated (say via a TCP/IP socket) to another C++ program residing on another machine. What do you suggest in such a scenario?
Edit:
To clarify, the functions which are to be moved are supposed to be pure and side-effect-free. So I do not have security or state-mismatch problems.
A solution to the problem is to build a small embedded domain specific language and serialize its abstract syntax tree.
I was hoping that I could find some language/library support for moving a machine-independent representation of functions instead.
Yes for function pointers and closures. Not for std::function.
A function pointer is the simplest — it is just a pointer like any other so you can just read it as bytes:
template <typename _Res, typename... _Args>
std::string serialize(_Res (*fn_ptr)(_Args...)) {
return std::string(reinterpret_cast<const char*>(&fn_ptr), sizeof(fn_ptr));
}
template <typename _Res, typename... _Args>
_Res (*deserialize(std::string str))(_Args...) {
return *reinterpret_cast<_Res (**)(_Args...)>(const_cast<char*>(str.c_str()));
}
But I was surprised to find that even without recompilation the address of a function will change on every invocation of the program. Not very useful if you want to transmit the address. This is due to ASLR, which you can turn off on Linux by starting your_program with setarch $(uname -m) -LR your_program.
Now you can send the function pointer to a different machine running the same program, and call it! (This does not involve transmitting executable code. But unless you are generating executable code at run-time, I don't think you are looking for that.)
A lambda function is quite different.
std::function<int(int)> addN(int N) {
auto f = [=](int x){ return x + N; };
return f;
}
The value of f will be the captured int N. Its representation in memory is the same as an int! The compiler generates an unnamed class for the lambda, of which f is an instance. This class has operator() overloaded with our code.
The class being unnamed presents a problem for serialization. It also presents a problem for returning lambda functions from functions. The latter problem is solved by std::function.
std::function as far as I understand is implemented by creating a templated wrapper class which effectively holds a reference to the unnamed class behind the lambda function through the template type parameter. (This is _Function_handler in functional.) std::function takes a function pointer to a static method (_M_invoke) of this wrapper class and stores that plus the closure value.
Unfortunately, everything is buried in private members and the size of the closure value is not stored. (It does not need to, because the lambda function knows its size.)
So std::function does not lend itself to serialization, but works well as a blueprint. I followed what it does, simplified it a lot (I only wanted to serialize lambdas, not the myriad other callable things), saved the size of the closure value in a size_t, and added methods for (de)serialization. It works!
No.
C++ has no built-in support for serialization and was never conceived with the idea of transmitting code from one process to another, lest one machine to another. Languages that may do so generally feature both an IR (intermediate representation of the code that is machine independent) and reflection.
So you are left with writing yourself a protocol for transmitting the actions you want, and the DSL approach is certainly workable... depending on the variety of tasks you wish to perform and the need for performance.
Another solution would be to go with an existing language. For example the Redis NoSQL database embeds a LUA engine and may execute LUA scripts, you could do the same and transmit LUA scripts on the network.
No, but there are some restricted solutions.
The most you can hope for is to register functions in some sort of global map (e.g. with key strings) that is common to the sending code and the receiving code (either in different computers or before and after serialization).
You can then serialize the string associated with the function and get it on the other side.
As a concrete example the library HPX implements something like this, in something called HPX_ACTION.
This requires a lot of protocol and it is fragile with respect to changes in code.
But after all this is no different from something that tries to serialize a class with private data. In some sense the code of the function is its private part (the arguments and return interface is the public part).
What leaves you a slip of hope is that depending on how you organize the code these "objects" can be global or common and if all goes right they are available during serialization and deserialization through some kind predefined runtime indirection.
This is a crude example:
serializer code:
// common:
class C{
double d;
public:
C(double d) : d(d){}
operator(double x) const{return d*x;}
};
C c1{1.};
C c2{2.};
std::map<std::string, C*> const m{{"c1", &c1}, {"c2", &c2}};
// :common
main(int argc, char** argv){
C* f = (argc == 2)?&c1:&c2;
(*f)(5.); // print 5 or 10 depending on the runtime args
serialize(f); // somehow write "c1" or "c2" to a file
}
deserializer code:
// common:
class C{
double d;
public:
operator(double x){return d*x;}
};
C c1;
C c2;
std::map<std::string, C*> const m{{"c1", &c1}, {"c2", &c2}};
// :common
main(){
C* f;
deserialize(f); // somehow read "c1" or "c2" and assign the pointer from the translation "map"
(*f)(3.); // print 3 or 6 depending on the code of the **other** run
}
(code not tested).
Note that this forces a lot of common and consistent code, but depending on the environment you might be able to guarantee this.
The slightest change in the code can produce a hard to detect logical bug.
Also, I played here with global objects (which can be used on free functions) but the same can be done with scoped objects, what becomes trickier is how to establish the map locally (#include common code inside a local scope?)

Is a templated, polymorphic callback a good idea?

I'm making a Gui Api for games. The user can always use inheritance on the widget and override, but I want callbacks. I want to use a templated callback system:
so if they want to have one for the mouse they inherit from a version of the templated callback base with mouseargs:
So the base would look like this:
template <typename T>
class AguiEventCallback {
public:
virtual void callback(AguiWidget* sender, T arg) = 0;
};
Is it a good idea to mix templates with polymorphism like this? Would I be better off creating callbacks for each of the types I need (mouse, keyboard, gamepad, etc)?
Thanks
Have a look at boost::function and boost::bind. Accept a function object with a defined parameter list for particular events, and callers can do what they want.
This gives callback implementations lots of flexibility and the object generating the events requires even less knowledge of the callback implementation.
For example:
typedef boost::function<void (AguiWidget* sender)> CallbackFunc;
void register_callback(CallbackFunc const& f);
And the client:
class Caller {
void do_register() { register_callback(bind(&Caller::event, this, 123, _1)); }
void event(int arg, AguiWidget* sender) { ... }
};
Just showing function/bind, many other issues ignored; eg. memory management, object lifetime.
Using a template the way you have is fine sometimes. There are issues due to the fact that you must give your template a virtual destructor and that
If you inline your virtual destructor (as you do with most template functions) some compilers find it hard to stick to the One Definition Rule, particularly if the library is used across libraries.
If you do not inline your virtual destructor you have to instantiate every type you are going to use with that template. This is my own preferred approach.
For a callback, you do have the option of using boost::function. This avoids having to derive classes from your template, create them with new and probably stick them into a shared_ptr somewhere. The downside of boost::function as a callback, I have found, is that it is harder to debug into if something goes wrong. Beware of that issue.
Momentarily accepting your virtual dispatch solution, what your templated approach guarantees is a uniformity in the callback function name and arguments. Sadly, that will force a lot of other code to disambiguate which callback is being invoked / overridden, probably causing more trouble than good.
That said, as janm said other options exist. Functors are more powerful (you can change them on an existing object at run-time, you can have lists of observers) but also have to be initialised at the right time (pure virtual functions effectively remind the programmer to supply them at compile time), and introduce a bigger variety of run-time states to reason about and understand.
You might also be able to use a template policy or the Curiously Recurring Template Pattern to supply behaviours at compile time, allowing inlining, dead code elimination, type-specific behaviours and other optimisations.
In addition to other answers here you might have a look to the boost::signal library. It implements a signal/slot mechanism which is indeed useful for GUIs. Performance is not as good as you would expect (costs more than a call to a virtual method) but for a GUI it's just fine.
The boost::signal library can also be used together with boost::bind and this combo is very powerful.
I don't like using inheritance very much for callbacks. It spawns a lot of classes with just 1 method most of the time. It's C++ not Java. you have functions, use them :)

Subscribe a button to trigger some function dynamically in C++?

I'm trying to make a button class (abstract) so I can set what function is that button going to trigger when clicked dynamically when my program load.
I want to construct all my buttons by reading XML files, this is to avoid code replication so having only 1 "generic" button class is really useful for me.
I was wondering if you could dynamically pass the necessary information about a method, like a pointer to the method's owner and method in question name, or even better the direct pointer to the method, for a button to call that function/method when clicked ?
Since pointer to function is a runtime artifact you cannot store that in the offline configuration. I see two solutions that might fit what you describe:
put your functions into a dynamic library and load them by name - that way your configuration would map a button to library path/function name pair,
build a "registry" of named function pointers at startup, probably some hash table, so the configuration would map a button to the hash key.
From experience though I would say that building such facilities are usually overkill, and the configuration quickly becomes heavier then the app itself.
Some additional pointers: Boost.Signals, QT Signals, Command and Chain of Responsibility design patterns.
You can create a SetFunctor method in your generic Button class, which accepts a function object as a parameter. Then you create a Call method that calls the function wrapped inside the function object. Something like this:
template<typename FUNC>
class Functor
{
typedef FUNC (*FC)();
FC func;
public:
Functor( FC f ) : func(f) {}
~Functor() {}
FUNC Call() { return func(); }
FUNC operator()() const { return Call(); }
};
class Button
{
std::auto_ptr<Functor<void> > pfunc;
public:
Button() {}
~Button() {}
void SetFunctor( void(*fc)() )
{
pfunc.reset( new Functor<void>( fc ) ); // now owns ptr;
}
void Call()
{
pfunc->Call();
}
};
...
void changeColor()
{
// do work
}
Button obj;
obj.SetFunctor( changeColor );
obj.Call();
Of course I could've used better smart pointers and or better techniques, but this should give you a gist of what I was hinting at. Also note, that this Functor object can only accept functions that have no parameters. You can change this to your liking. I hope it helps!
UPDATE: A few fixes added. Sorry about that!
You are looking for the signal/slot pattern.
In C++ two popular options are boost signals and sigc.
There are a couple of ways to link a button to a function in C++ - you can use function pointers (which are somewhat scary), or a signals and slots pattern which provides the functionality of function pointer with more type safety.
As far as wiring up the function pointers or signals and slots at run time based on a config file, to do this elegantly will require reflection, which C++ doesn't provide for you. I suspect this will be the ugly part.