free c++ plugin system

Started by
8 comments, last by njpaul 16 years, 9 months ago
Hi all, I'm looking for a free, platform indipendent plugin system for c++, that let me to additional components for my application. I've seen a couple of them, but I want to know your opinions. Easier is better, because I think to that as a required step, but would prefer to spend my time on the project itself rather on learning to use the plugin system:-) Thank you!
Advertisement
What is your project about?
The thing is that I've never seen any "common plugin system".

The easiest "plugin system" are the basics of Windows:

HMODULE WINAPI LoadLibrary( LPCTSTR lpFileName );
FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR lpProcName );
BOOL WINAPI FreeLibrary( HMODULE hModule );

What it is in linux I don't know.
My spacesim project blog:http://www.simerge.com/
I don't know of any freely availble plugin system; yet it only takes a matter of minutes to create one. It would be advisable to understand how and what works across dynamic boundries and this time spent will save you alot of problems. Here is a few links to get you started and don't be so lazy :(
http://www.nuclex.org/articles/building-a-better-plugin-architecture
http://aegisknight.org/cppinterface.html
http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/C++-dlopen-mini-HOWTO.html
http://msdn2.microsoft.com/en-us/library/ms682599.aspx

Thank you both. Well, I've already used external dll in past projects. It's just that I want to stay platform agnostic the most I can. What I'm doing is redesign my raytracer, and since I would to make it expandable by plug-ins (new objects, textures, lights, shaders, etc.), I think that this is a thing that I should already consider before starting to design it. But of course, considered the small amount of sparetime, I want to spend it on the renderer...

@dmail: yep, it is not laziness at all :-) I would very pleased to study in depth all those things, but I'm more interested in graphic, and plugins just happen to be highly useful in these systems. In addition, I'm keeping my code far from SO peculiarities, so it should be compilable on every platform so far. The problem is that I don't know how to load .so libraries, and creating a system for mysel would require me to study even this...That said, I will look into your links, and actually I've already read a coulple of them before asking here on gamedev.

If you have other informations, please let me know.
Quote:I don't know of any freely availble plugin system; yet it only takes a matter of minutes to create one. It would be advisable to understand how and what works across dynamic boundries and this time spent will save you alot of problems. Here is a few links to get you started and don't be so lazy :(


While it's true that coding isn't much more than:
class PlugIn {  virtual void initialize();  virtual void shutdown();}class PlugInManager {  bool install( std::string pluginName );  ...}


Designing a good general purpose plugin system is hard. Unless you specify it for a particular task, you'll need to invent a lot of systems, cross-plugin communication, incredibly complex life-cycle management, interospection systems, and more.

COM/DCOM and their other incarnations are a decent Windows solution. Complex, annoying and extensive, but still, they cover just about all ground.

But mostly, given the static nature of C++, plugin architectures are, without an incredible amount of effort, simply not worth it. C# and Java offer out-of-box run-time pluggable architectures with all the facilities one could need.

This in part contributed to popularity of Java-based web frameworks (run-time hot-swap plug-ins).

Dynamic libraries are the basic solution, as long as you don't push things too hard.
Quote:Original post by Antheus
Dynamic libraries are the basic solution, as long as you don't push things too hard.


I'm not sure about what you mean exactly... dynamic libraries is just what I want. For example, I want to add a procedural texture to the raytracer. I write it deriving from the ProceduralTexture base class and put it in a dll. Then I put the dll in the "plugins" directory of the application. When the app starts, it registers any available plugin and make the new class MarbleTexture available to the raytracer...
I thought about a general plugin class that has a few methods like:

char* PluginType()
void* CreateObject()

Each plugin must implement this class: in this case:

char* Plugin::PluginType(){return "TEXT_PROCEDURAL";}void* Plugin::CreateObject(){return new MarbleTexture;}


There are others utility methods, of course, but this is how I thought it. Could this be a (decent) way of doing this?
Quote:There are others utility methods, of course, but this is how I thought it. Could this be a (decent) way of doing this?


With dynamic libraries and static typing, the interfaces with which you interact with objects created by plugin are fixed.

For example, in a renderer, you'll call the library, and obtain a void *pointer. You'll assume that it's something you can use.

A generic plug-in design would allow your renderer to submit its context to the library, then let library execute the functions. Once you go into big picture design, you realize that the only way to develop a scalable plug-in system, is to used concepts like Command, Visitor and Inversion of Control.

void* Plugin::CreateObject(){return new MarbleTexture;}


Here, you need to define the Texture interface. What happens, if you then want to add an advanced texture in a different plug-in? Marble, Wood, ... textures are all exactly the same, they merely define some parameters. What if you want your texture to calculate reflection?


We're talking ray-tracer here...

Breaking it down into functional layers - what is the very essence of a ray-tracer?

- Rays

This way it becomes possible to design a context specific plug-in system that brings this knowledge into design.

When rendering, you create an instance of ray. You then traverse the scene-graph, searching for collisions. On collision, you perform a set of operations, push the results on stack, and continue traversal. When complete (expired, hits light, skybox, ...), you return, and post-process the resulting stack.

An extensible plug-in system here would catpure this functionality. Each plug-in will need basic knowledge of the world (Ray - accessing, creating and casting new, world - querying for interactions with rays).

Your plug-in system would therefore not provide an abstract texture, but the texture handler would be attached to an object. On collision, you call this texture handler, to provide you with result of ray-texture interaction. Even better, let the "material handler" take care of further ray-casting.

Your plug-in system then becomes something like this:
ResponsePlugin{  OutBoundRays collision( InboundRay, Object );}ProcessorPlugin{  process( InboundRay, OutBoundRays, Object, RayCastResult );}PostProcessPlugIn{  Pixel process(RayCastResults);}


When you create a scene, each object will have default handlers for both. You can then add custom handlers (each in their own plug-in) to handle collisions differently.

This way, you do not need to pass any internal knowledge across plugins, yet still have full control over rendering process.

Your plug-in API can then be expressed as a set of ray-tracing operations. Pixels, Rays, Objects, and ray-casting collision calculations.

Textures, primitives (collision detection also becomes plug-in system to allow creation of arbitrary geometries), calculating reflection, refraction, texture response, shaders(kinda), ... all become plug-ins, without any of them knowing about each other.

If you expose internal details from plug-ins, you'll quickly find the plug-in system isn't pluggable at all.

With such function-oriented system, you can customize every tiny aspect of rendering, and the only penalty you need to pay (not negligible, but managable), is the cost of transporting your ray information across separate modules, while retaining full and complete customizability of the system.
Quote:Original post by Antheus
Quote:There are others utility methods, of course, but this is how I thought it. Could this be a (decent) way of doing this?


With dynamic libraries and static typing, the interfaces with which you interact with objects created by plugin are fixed.
...


Yep, perhaps I was not clear, and I think that what you explained is more or less what I was thinking of: my example only focused on the library integration. Of course the MarbleTexture is a texture with a well known, well specified interface. For example, it has a SurfaceColor(float u, float v) that returns the color of the texture (u,v) coords. But since I didn't design the object (I'm working with mu old RT in order to better define my needs) this was only an example. What I meant to ask, is if once I decide what is the interface of an object (and thus what it is allowed to do and what not), is that way a good (well, good enaugh) solution?

EDIT: Just to be clear, I'm perfectly aware of the fact that I will limit somehow what the objects in the library can do. I don't intend to give them full access to every component of the raytracer, and I'm fine with this. They will be able to shoot rays in the scene and make use of global settings, not much more. The actual amount of freedom to give to the modules has not yet been identified. I'm following a good book as the source for inspiration for my architecture...
Try this one http://msdn.microsoft.com/msdnmag/issues/05/10/CatWork/
may be helpful for you.
I've written a platform independant plugin system based off of this article. It works very well and is relatively easy to implement.

This topic is closed to new replies.

Advertisement