How to Implement a C++ Plugin System for a Modular Application? - c++

I am trying to design a modular application; one where developer's create plugins as dlls that get linked to the main application using loadlibrary() or dlopen(). My current thoughts on this are:
1: Both the application and plugin module include a core header with a pure virtual class IPlugin with a method run(). The plugin module then implements the class, defining run():
2: The plugin module defines a function IPlugin* GetPlugin() using "extern c" to ensure ABI compatibility
3: The application requires the plugin module using loadlibrary(), retrieves IPlugin from GetPlugin() using getprocaddress()
4: The application calls method run() to run the plugin
This all works, but how do I create a plugin interface that has access to my full application code? If I have a class that creates a window or initializes a button, I want to access those through the plugin interface and be able to manipulate them and receive events, while still having the memory be managed by the main application side.
1. How would I go about doing this?
2. Would the best solution be ABI compatible?

An API either uses C++ or C, there’s no middle ground. If you want to force plugin developers to use an ABI compatible compiler then you can have an interface that deals with classes and virtual methods and there’s no need for any “extern C” brouhaha.
Otherwise, you’re providing a C API and a C API only. Of course you can implement a virtual function table using a struct of function pointers, and internally you can wrap it in a C++ class and whatnot. But that’s your implementation detail and doesn’t figure in the design of the plugin interface itself.
So that’s that, pretty much. There’s no such thing as C++ API compatibility for free on Windows. People use at least 5 incompatible compilers - MSVC 2017+, 2015, 2012, mingw g++ and clang. Some particularly backwater corporate establishments will insist on using even older MSVC sometimes. So a C++ interface is mostly a lost cause unless you provide shims for all those users. It’s not unthinkable in these days of continuous integration (CI) - you can easily build wrappers that consume your C API and expose it to the users via a C++ interface compatible with their preferred development system. But that doesn’t mean that you get to mess with their C++ objects directly from your C++ code. There’s still a C intermediary, and you still need to use the helpers in your adapter code. E.g. you cannot delete the user provided object directly - you can only do it by calling a helper in the adapter DLL - a helper that uses the same runtime and is ABI compatible with user’s C++ code.
And don’t forget that there are binary incompatible runtime libraries for any given compiler version - e.g. debug vs release and single vs multithreaded. So, for any MSVC version you have to provide four adapter DLLs that the plugin developers would link with. And then your code links to that adapter as well, to access user’s plugin. So you would be first parsing the binary headers in the plugin to determine what adapter DLL and runtime it’s using, and issue an error message if they don’t match (plugin devs are very likely to mess up). Then if there’s a match you load the plugin DLL. The dynamic linker will bring in the requisite adapter DLL. Then you’re ready to use the adapter DLL to access the plugin.
Having done this before, my advice is to have each adapter dll provide different C symbols to your host program, since invariably there will be multiple plugins each using a different adapter and this only complicates matters. Instead, you need to link to all the adapters via demand loading on Windows, and only access a particular adapter when you have parsed the plugin DLL to know what it’s using. Then when you call the adapter, the dynamic linker will resolve the demandload stubs for the real adapter functions. A similar approach can be used on non-Windows platforms, but requires writing helper code to provide the demand link feature - so it may be simplest to use dlopen explicitly on Unix. You’ll still need to parse the ELF headers of the plugin to figure out the C++ runtime it uses and the adapter library it expects, validate the combination; and only then load it. And then you’d dlopen the adapter to talk to the plugin. In no case you’d be directly calling any functions on the plugin itself - only the adapter can do that safely when you need to cross C++ runtime boundaries. There may be easier ways to do all that but my experience is that they only work 99% of the way so in the end there’s no cheap solution here - not unless someone wrote an open source project (or a product) to do all this. You will be expected to understand the dirty implementation details and deal with C++ runtime bugs anyway if you dabble in that. So if you’d rather avoid all that - don’t mess with C++ user visible APIs that require lodable libraries.
You can certainly do a header only C-to-C++ bridge for the user, but surprisingly enough some users don’t like header only solutions. Sigh. How do I know? I had to get rid of a header-only interface improves customer insistence… I wept and laughed like a maniac all at once that day.

Related

Simplest way to write cross-platform application with Python plugin extensibility?

I am writing an application which should be able to run on Linux, Mac OS X, Windows and BSD (not necessarily as a single executable, so it doesn't have to be Java) and be extensible using simple plugins.
The way I want my plugins to be implemented is as a simple Python program which must implement a certain function and simply return a dictionary to the main program.
Plugin installation should just be a matter of copying the plugin script file into the ./plugins directory relative to the main executable.
The main program should be a stand-alone executable with shared code amongst all of the above platforms, but with platform specific front-ends (so the Linux and BSD versions would just be CLI tools, the Windows version have C++ and MFC front-end, and the Mac OS X version would have a Objecive-C and Cocoa front-end).
So I guess it's really two questions:
What's the simplest way to share common controller code between multiple front ends from:
a. Objective-C on a Mac?
b. C++ on Windows?
c. C/Python from Linux/BSD?
What's the simplest way to implement plugins from my common controller to execute custom plugins?
I am with fontanini here; use shared libraries (DLLs) for the controller logic. Preferably, use C/C++ for that, and be careful with RTTI (needed for dynamic_cast<> and exception handling), which may not work across DLL borders (e.g. you might have problems catching exceptions thrown in one DLL from another one).
Look for good cross-platform libraries like Qt, which offer a lot of functionality (e.g. filesystem, processes, networking – not just GUIs, which you want to develop separately anyhow) in a platform-agnostic way.
The Python/C API is the basis for making C/C++ functionality available to Python (and vice versa), and there is only little difference between extension modules and programs that offer their own functionality to an embedded Python interpreter.
However, you might want to use a wrapper generator (all of which are based on the Python API, but require less code than using it directly) that makes your life easier. Examples are:
boost::python (which is very convenient and powerful, but has an incomprehensible hardcore-C++ implementation ;-), and leads to larger object code due to excessive template usage), possibly using pyplusplus to generate the boost::python wrapper code directly from your header files (not sacrificing the possibility to tweak the result, e.g. excluding or modifying function signatures)
SIP (in particular in conjunction with [Py]Qt, for which it was developed)
Swig (which is suitable for multiple scripting languages, but leads to APIs that rather mirror the C APIs being wrapped instead of being "pythonic")
PyBindGen which is based on the same GCCXML backend as pyplusplus, but generates pure Python/C API code directly, leading to leaner bindings (but may not grok all code out of the box)
The simplest way to share the cross-platform Python component of your application would probably be to implement it as a command-line program, and then invoke it using the relevant system calls in each of the front-ends. It's not the most robust way, but it could be sufficient.
If you want plugins to just be a file containing Python code, I would recommend that they at least conform to a convention, e.g. by extending a class, and then have your code load them into the Python runtime using "import plugin_name". This would be better than having the plugins exist as separate programs because you would be able to access the output as Python types, rather than needing to parse text from standard input.

what's the best way to write a pluginable application?

I want to write a native application that can be extended with plugins, perferabily in the form of dynamic libraries. I have an idea of what to do, but I would like some ideas, especially best practice tips on what to do and not to do. I worked with similar things on java and php, so I hope I don't bring any bad habits in to my C++.
I'm thinking of allowing developers to implement certain functions like "on_recieve_data(App* app, void* data)" and my application will load all the plugins and call their on_recieve_data function with a pointer to itself (dlsym?).
There are a few things that I consider very important for plugins:
Language support
If you want to reach the most number of platforms/languages/compilers then you should write the plugin interface in C and not in C++. The plugin developers can still write their functions in C++, of course, it is just the interface that is C. The problem is that each C++ compiler mangles symbol names in its own way, so if you use C++ you will be forcing plugin developers to use the same compilers and tools that you use. On the other side, there is only one way to export C symbols, so using a C interface for the plugin will allow developers to pick whatever tools they like, and as long as they can produce standard .so/.dll libraries they'll be fine.
Memory allocation
In some platforms there are problems when memory allocated by the application is released by a DLL or viceversa. If the plugin has functions that are supposed to allocate memory, then make sure you also require the plugin to provide a corresponding function to release that memory. Likewise, if the plugin can call a function in the application to allocate memory, you should also expose a release function for that memory.
Versioning
It is likely that you will have to revise the plugin API after plugins have been written. So your application needs to be prepared to load plugins developed for an older version. You should require an 'init' function in the plugin that the application calls to determine what version of the API the plugin implements and any other information the app might need to know, like the plugin type (if there are different types), what is implemented and what isn't, etc.
Also you have to be very careful when you have to revise the plugin API. You can't change existing functions, since that would break older plugins. Instead you will need to add alternative versions of those functions that have the improvements. Then the problem comes of how to name the new version of an existing function. Typically they'll get the same name plus some suffix ('Ex', a number, etc.). I haven't seen this problem solved in a way that I like.
Likewise, you have to take precautions for structures that are passed between the application and plugins. A common approach is to make the first member of all structures the size of the structure. This works as sort of a versioning mechanism, so that the application can determine what the structure looks like from its size.
Here are a few links that might be of interest:
C-Pluff, a general purpose plug-in framework in C (MIT license)
lighttpd's plugin.h header file
This page has a discussion on how to implement a plugin architecture under Mac OS X, including a short overview of a how to create a C interface for plugins.
Blender is an interesting one. The application is written in C++, but plugins are written in Python. Not a bad idea really, it makes it a lot easier for developer to write plugins.
There are plenty of applications written in scripting languages that support plugins (Wordpress, Drupal, Django, and many more). You can look at any of those that are closer to the kind of application you are writing for ideas.
I believe that this post -> Design Pattern for implementing plugins in your application? does answer your question I guess. It has a lot of refernce for plugin model.
Perhapse, the Eclipse architecture can serve as example:
http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html
I'm pretty there is a book from Eclipse's creator, but I can't remember neither the author nor the name of the book.

What's the simplest way to write portable dynamically loadable libraries in C++?

I'm working on a project which has multiple similar code paths which I'd like to separate from the main project into plugins. The project must remain cross-platform compatible, and all of the dynamic library loading APIs I've looked into are platform specific.
What's the simplest way to create a dynamic library loading system which can be compiled and run on multiple operating systems without extra modification of the code? Ideally, I'd like to write one plugin, and have it work on all the operating systems the project supports.
Thanks.
You will have to use platform dependent code for the loading system. It's different loading a DLL on Windows than loading a shared object in Unix. But, with a couple of #ifdef you will be able to have mostly the same code base in the loader.
Having said that, I think you can make your plugins platform independent. Of course, you will have to compile it for every platform, but the code will be 99% the same.
Dynamic library loading an Windows and Unix/Linux works with 3 functions. A pair of functions to load/unload the libraries, and another function to get the address of a function in the library. You can easily write a wrapper around these three functions to provide cross operating systems suppport.
Ideally, I'd like to write one plugin, and have it work on all the operating systems the project supports.
Few things from top of my head:
Avoid static objects in the dynamic libraries. Provision proper initialization methods/functions to allocate the objects. The issues which occur during library being loaded by the OS (this is when the c'tors for static objects are called) are very hard to debug - next only to the multi-threading issues.
Interface headers may not contain code. No inline methods, no preprocessor defines. That is to avoid tainting application with the code from particular version of library, making it impossible to replace the library at later time.
Interface headers may not contain implementation classes themselves - only abstract classes and factory functions. Similar to the previous point - to avoid application depend on the particular version of the classes. Factories are needed as a way for user application to instantiate the concrete implementation classes.
When introducing new version of an interface, to keep things somehow backward compatible, do not modify existing abstract class - create new abstract class inherited from it and add new methods there. Change factory to return the new version. (Recall MS' IInterface, IInterface2, IInterface3 and so on.) In the implementation, use newer version of the abstract class. That by polymorphism would make the implementation backward compatible with the older interface versions. (That obviously calls for periodic interface maintenance and clean-ups - to remove the old cruft.)
Take a look at the boost.extension library, it is not really part of boost, but you can find it in the sandbox. It is kind of frozen also, but overall the library is stable and easy to use.

Implementing A Plugin System in C or C++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
What are your tips on implementing a plugin style system?
In C (and I think C++ too although I haven't done it myself), this is most typically done using dynamically loaded modules. The API:s for such are platform-dependent.
On POSIX (Linux), you use the dlopen() family of functions. Basically you build your plugin separately, then load it at run-time, look up its symbols by name, and can then call them.
For Win32, there is LoadLibrary() which does something very similar, you build your code into a DLL.
For a handy wrapper that makes all of these easy and transparent, check out GLib's GModule API.
In the '92/'93 time frame I worked on a plugin architecture for Aldus PageMaker, which was coded in C++. PageMaker was built on a C++ OOP framework called VAMP, which assisted its portability between Mac OS and Windows.
So we tried to use the features of C++ to build a plugin architecture. This proved to be very problematic for C++ classes due to the so-called brittle base class problem. I proceeded to write a paper that was published in journals and that I presented at OOPSLA '93 in a reflection workshop. I also made contact with Bjarne Stroustrup at a Usenix conference in Portland and proceeded to dialog with him for several months, where he championed the issue of dealing with the brittle base class problem on my behalf. (Alas, other issues were deemed more important at that time.)
Microsoft introduced the COM/DCOM system and for that platform that was looked on as a viable solution to the problem. C++ could be used as an implementation language for COM via abstract classes used to define COM interfaces.
However, these days developers shun away from COM/DCOM.
In contrast, NeXT devised a plugin architecture using Objective C in the early 90s in the NeXT Step framework. Today that lives on vibrantly in Mac OS X on Apple's computers and important platforms such as the iPhone.
I submit Objective C enabled solving the plugin problem in a superior manner.
I personally regard the brittle base class problem of C++ to be it's most fatal flaw.
If were building a plugin architecture with the C-based family of languages, would do so using Objective C.
The best platform and language neutral advice I can give is this:
Design your entire app around the plugin SDK.
IMO, a plugin SDK should not be an afterthought. If you design your app to basically be an empty shell which loads plugins, then the core features are implemented in your own SDK, you get the following benefits:
High modularity of components, and clear separation of purpose (it kind of forces your architecture to be good)
It forces your SDK to be really good
It allows other third party developers to make extremely powerful, core-level features as well
New developers/hires can easily start work on a major new feature without having to touch the main app - they can do all their work in a plugin (which prevents them screwing up anything else)
In C/C++, you probably use dynamic link libraries and either function pointers (C) or interfaces (classes solely consisting of pure virtual methods, for C++). However even if you use Javascript, I'd still recommend the above architecture.
Qt provides QPluginLoader:
http://qt-project.org/doc/qt-4.8/qpluginloader.html
If you need/want more fine grained control, Qt also provides a means to load libraries on the fly with QLibrary:
http://qt-project.org/doc/qt-4.8/qlibrary.html
Even better, these are portable across platforms.
This may not be what you're looking for, but you could embed a scripting language in your application, such as Lua. Lua was designed to be embedded in other programs and used as a scripting language for writing plugins. I believe it's fairly easy to add the Lua interpreter to your program, though I don't know Lua so I can't vouch for how effective of a solution this would be. Others with more experience with Lua, please add comments about your experience with embedding Lua in another application.
This would, of course, mean that your plugins need to be written in Lua. If you don't like Lua then the de-facto standard Perl, Python and Ruby interpreters are all written in C, and can be embedded in a C program. I know of a number of programs that use these languages as scripting language extensions.
However, I don't know what you're looking for, as your question is a little vague. Perhaps more information about what you want people to be able to do with said plugins would be appropriate. For some tasks, a full-blown scripting language may be a bit overkill.
I have written an article about how to implement a plugin system using Dynamic Linking Libraries. The article is written from the point-of-view of a Windows programmer but the technique can be applied to a Linux/Unix type environment.
The article can be found here: http://3dgep.com/?p=1759
The main point is, you should create a "common" DLL that is implicitly linked by both the main application (the core application) and by the plugin implementations. The plugins can then be explicitly linked and loaded dynamically at run-time by the core application.
The article also shows how you can safely share static (singleton) instance of a class across multiple DLLs by using the "common" DLL.
The article also shows how you can export a "C" function or variables from a DLL and use the exported functions in the application at run-time.
It's best to use a framework like ACE (http://www.cs.wustl.edu/~schmidt/ACE.html) that shields you (as good as possible) from platform specific coding.
ACE contains a plugin framework that is based on shared libraries that you can use to create dynamically assembled applications.
For a higher level abstraction check out CIAO (http://www.cs.wustl.edu/~schmidt/CIAO.html) the Open Source C++ implementation of the CORBA Component Model.
Look at Poco Class Loader, it can be interesting for you.
I have written a plugin library Pugg that loads C++ classes from dll files and here is the logic I used:
User exports a c function from dll that has a unique name. This name has to be unique enough as functions cannot be distinguished using their arguments while loading from dlls.
C function registers one or several factory classes called "Driver". Every Driver class is associated with a string. When the main application wants to create a class, it gathers the related factory class using the associated string. I also implemented a version checking system to not load old plugins.
Dll loading is accomplished using the LoadLibraryA and GetProcAddress functions (Pugg currently works on windows).
One thing worth mentioning is that main application and dlls should be compiled using the same compiler and using the same compilation options (release/debug modes, optimization settings, stl versions etc...). Otherwise there might be issues with mapping of classes.
I have had some success using a fairly naive system:
Create API Specification for plug-ins
Use a singleton plug-in manager
Use LoadLibrary/GetProcAddress based run time dynamic linking
Implement Inversion of control based event handling for notifying the plug-ins
This podcast on plugin architectures might also be interesting.

What's safe for a C++ plug-in system?

Plug-in systems in C++ are hard because the ABI is not properly defined, and each compiler (or version thereof) follows its own rules. However, COM on Windows shows that it's possible to create a minimal plug-in system that allows programmers with different compilers to create plug-ins for a host application using a simple interface.
Let's be practical, and leave the C++ standard, which is not very helpful in this respect, aside for a minute. If I want to write an app for Windows and Mac (and optionally Linux) that supports C++ plug-ins, and if I want to give plug-in authors a reasonably large choice of compilers (say less than 2 year old versions of Visual C++, GCC or Intel's C++ compiler), what features of C++ could I count on?
Of course, I assume that plug-ins would be written for a specific platform.
Off the top of my head, here are some C++ features I can think of, with what I think is the answer:
vtable layout, to use objects through abstract classes? (yes)
built-in types, pointers? (yes)
structs, unions? (yes)
exceptions? (no)
extern "C" functions? (yes)
stdcall non-extern "C" functions with built-in parameter types? (yes)
non-stdcall non-extern "C" functions with user-defined parameter types? (no)
I would appreciate any experience you have in that area that you could share. If you know of any moderately successful app that has a C++ plug-in system, that's cool too.
Carl
Dr Dobb's Journal has an article Building Your Own Plugin Framework: Part 1 which is pretty good reading on the subject. It is the start of a series of articles which covers the architecture, development, and deployment of a C/C++ cross-platform plugin framework.
You might also want to consider replacing the conventional plugin interface by a scripting interface. There are some very good bindings for several scripting languages in C/C++ that have already solved your problem. It might not be a bad idea to build on top of them. For example, have a look at Boost.Python.
Qt has a very nice system for plugins that I've used in the past. It uses Qt's meta-object system to overcome many of the problems typically found when trying to develop C++ plugins.
One example is how Q_DECLARE_INTERFACE works, to prevent you from using an incompatible plugin. Another is the build key, to make sure you load the correct plugin for your architecture, OS, compiler. If you don't use Qt's plugin system, these are things you will have to worry about and invent solutions for on your own. It's not necessarily rocket science, and I'm not saying you'd fail at it, but the guys at Trolltech are pretty smart and have spent a while thinking about it, and I'd rather use what they created than reinvent the wheel myself.
Another example is that RTTI typically doesn't work across DLL boundaries, but when using Qt, things like qobject_cast which rely on the meta-object system do work across DLL boundaries.
I think you are safe creating a plugin system based on:
Packaging of plugin functionality into library (.dll, .so, etc.)
Requiring that the plugin expose key C-language exports.
Requiring that the plugin implement (and return a pointer/reference to) an abstract C++ interface.
Probably the most successful C++ plugin system: good old Adobe Photoshop. And if not that, one of the virtual synth formats such as VSTi etc.
The book Imperfect C++ by Matthew Wilson has a nice info about this.
The advice in the seems to be: as long as you use the same (or equivelant) compiler, you can use C++, otherwise you're better of using C as an interface on top of your C++ code.
I have my own game engine that has a C++ plug-in system.
I have some code in header files so it gets put into the plugin's compilation unit.
Larger functions that live in the main engine are called via an exported C function (plugin calls MyObject_somefunction(MyObject *obj) which in the engine just calls obj->somefunction()). If calling a C function is ugly for your taste, then with some header trickery, when the header is included in the plugin, have the member function #defined to call the C function:
#if defined(IN_THE_PLUGIN)
void MyObject::somefunction() { MyObject_somefunction(this); }
#endif
Virtual functions either have to be pure or the code lives in the header file. If I'm not inheriting from a class and merely just instancing one, virtual function code can live in the engine, but then the class must export some C functions for creating and destroying the object that is called from the plugin.
Basically, the tricks that I have used, with the goal being to maintain total platform independence, just amount to C exports and header file tricks.
ACE has a cross platform plug-in architecture.
Check out:
ACE DLL
ACE DLL Manager
I would suggest checking out the book
The ACE Programmer's Guide
Firefox runs on XPCOM (http://www.mozilla.org/projects/xpcom/). It's inspired by Microsoft COM but it's multiplatform.