Ok so I have this project in ming for along time now. Basically I have created a console app that works as a calculator by using mathfunctions from a DLL I also have created. Now the problem is I want to make it so that people can create their own DLLs with mathfunctions and install them to my app.(Offcourse nobody would do that but I only want this for educational reasons :))
Could you help me or point me to the right direction please maybe not a DLL plug in system but any other plug in system.

How would you go about it?

With regards,

7 Years
Discussion Span
Last Post by stavros141

First of all, this is highly dependent on the capabilities that you want your plugin system to be able to handle. It can range from a very simple set of capabilities, leading to a fairly easy task to accomplish, to a very comprehensive set of capabilities, leading to a very very difficult task to accomplish.

Simplest case:
If all you want is for your plugin to be a DLL that provides a certain set of functions, then it is pretty easy to do. For example, imagine that the plugin's sole purpose is to load a sound file and play it. You could define a certain number of standard functions (like LoadAudioFile(), PlayAudio(), PauseAudio(), StopAudio(), etc.). Then, in your application, given a DLL, you have to load it dynamically (with LoadLibrary() (windows) or dlopen() (linux)), get function pointers for each of the standard functions (with GetProcAddress() (windows) or dlsym() (linux)), then, if all the pointers are non-NULL (i.e. they all exist in the DLL, or at least, a non-optional subset of them), you can use those function pointers to execute the functionality from the DLL, and finally, when done with it, you free the DLL (with FreeLibrary() (windows) or dlclose() (linux)). And that's it, pretty much.

Complex case:
If you want your plugin to provide an extensible set of functionalities and possibly an extensible set of classes, then it becomes much harder. I have done this in the past and it is very difficult to do correctly (I barely "succeeded"). If all you want is an extensible set of functionalities, then you can provide some sort of standard set of function prototypes (i.e. specifying the types and number of parameters and return type that functions are allowed to have). Then, you will need a function that gives the application a list of all the functions that are available in the DLL along with the prototype. For example, it can be in the form of a string with a special format that. Say I wanted to do a plugin system for doing some calculation with matrices, I could define some standard prototypes like "MatrixBinaryOperation" and others, then the plugin could provide a function called "MultiplyMatrices" that takes two matrices, multiplies them together and outputs a resulting matrix (that would be a binary operator). In that case, my standard plugin function could output a string like "MatrixBinaryOperation MultiplyMatrices;" that tells the main application to load a function called "MultiplyMatrices" that has the standard signature of a "MatrixBinaryOperation". Then, all you have to do is add a few extra steps to the method I explained under "Simple case" where you load the DLL, get a function pointer for the standard function, get the formatted string, parse it for all the functions that are made available by the plugin, then construct the lists of function pointers for those functions, and get their addresses from the DLL.

If you want extensible classes to be published by your DLL, then that is a whole different ball-game. The procedure of creating a plugin and loading it from the main application would be similar to the above two cases, but using objects and calling virtual functions on them is a lot different than using simple function pointers. You will have to worry about:

- Application Binary Interface (ABI): this is basically the problem that classes, when compiled, will produce objects that look differently in memory (data members may not be aligned the same way, may not be ordered the same way, the virtual-table might be somewhat different, etc.) from one compilation to another (e.g. if the compiler is different, if the compiler version is different, if the compiler options used are different, etc.)

- Cross-module Memory Management: the main problem here is that memory allocated from a DLL cannot, in general and reliably, be deallocated from the main application, because they use different heaps, This requires a certain amount of care in designing functions to avoid this problem. Also it requires special care with automatic copies and automatic deletion of objects (going out-of-scope). It also requires special care about inline functions (especially virtual ones), and so on.

- Cross-Module RTTI (Run-time type identification): the C++ RTTI (you know, the thing that is necessary to be able to use typeid() and dynamic_cast) is not shared across module. This means that if you need to perform, from your main application, a dynamic cast on an object pointer that was created from a plugin DLL, you will most probably crash your application (at least, this will be a horrible case of "undefined behaviour"). So, if you need RTTI (and you will if you do serialization for example), then you will need to make your own.

- Shared Global Data: some platforms support the dynamic linking of global extern variables (Linux does), but Windows does not. This means that each application or DLL that is loaded will each have their own global variables. So, if you need some variables to be shared globally by all DLLs and the main application (which you need for RTTI for example), you will need to implement a cross-module singleton (which is not a trivial task).

And, I'm probably forgetting other issues, but these are the main ones.

One example of an off-the-shelf solution is Microsoft's COM and ActiveX components, which is basically an implementation for the most complex case that I mentioned above. This is a heavy and platform-specific solution, so it rarely is the most appropriate, but it is good to understand the way they do it, and why.

Votes + Comments
Nice break down
Nice post.

Thank you for your answer mike it is really helpful. That certainly helps me to start. :D

Thanks a lot !!!

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.