Programming for plugins

cfleck

tired
This isn't so much a mac-related question, as just a programming question in general.

How does one go about designing a program to utilize after-the-fact plugins. I have an idea for an application that I'd like to create, and it seems to be an ideal candidate for plugins. Problem is, I have no idea how to go about creating a program that can utilize such things, much less how to create the plugins themselves.

Any direction here would be much appreciated.
 
A plugin is basically a piece of code loaded dynamically at runtime. In other words, it's the layman's term for "dynamically loaded library." Don't freak out when you hear DLL :p Macs have them too, they have the *.dylib extension.

There are a few steps involved to create an application that supports plugins. I'll just go over the concepts, since you opened this up as not Mac-specific.

1. Your main application needs to be designed in a way that allows for customization. Take for example, if you were making an MP3 player. What elements in the app can you "expose" to plug-in writers so they can enhance it in their own way? Suppose they want to add different popup windows, like a mixer, or a window that goes online and tries to find song lyrics and display them. Any new interface elements have to become children of the parent window (the media player). So the main app itself has to have a mechanism for allowing new windows to be created on the fly, and take ownership of those windows.

Lets also look at customizing the look of the app. You could expose the sudo LCD screen so that developers can write plugins that enhance the look or behavior of that LCD display. The LCD display window itself is probably just a plain ol' borderless child window. You can allow people to handle the drawing routine on their own and let them be creative with it. But whatever "freedom" you choose to allow, it has to be made available. So we established that the main app has to have in-roads for customization.

2. How? More technically, you probably need to create one library of rountines that both the main app and plugins will link against. That is how both pieces of software will become aware of what the other can do. It's the hook up.

For example you might need 2 routines: OnLoadPlugin() and OnUnloadPlugin(). Those will handle the loading and unloading of that particular plugin, initialization and clean up. Both the main app and the plugin have to be aware that those are the function names, that is why we need to create a library that they both link against. So they both understand that those are the function names, and when it is appropriate to call them. The main app itself may end up being the one that calls those routines, but the rountines are actually residing in the plugin code.

This works much better if you are developing with an object oriented language like Objective-C or C++. You create a base class, all plugins have to be a subclass of the base class. The init and clean up routines will be member functions. The main app will maintain a list of all those objects loaded. But those member functions should be declared in the base class. That way they're available to all subclasses, but implemented differently (after all, plugins do different things). So now, without actually knowing what that new subclass is, the main app at least knows that it is a subclass of the base plugin class. It can still call routines that are declared in the base class. That's how your main app can talk to the plugin without knowing what it really is, it's the dynamic nature of object oriented programming. It is up to you to create those in-roads for that communication to be possible.

3. The plugins themselves are little libraries. A library is not a seperate program, it does not have a running process. Instead, it gets loaded into the memory space of an existing process. That process can then use the code inside the library as its own. Specifically to MacOS programming, there are routines both in Carbon and Cocoa to load dynamic libraries and call upon the code within. I only saw them briefly but they seem to work very similar to the routines I'm more familiar with in Windows programming.

Suppose you create a subclass of your base plugin object and put it in this new library (plugin). But your main app doesn't know what this plugin is, the subclass' class declaration is not included in any of your app's header files. This is the way is should be, static declarations kind of defeats the point of dynamic loading plugins. This goes back to the need for a base plugin class. Inside your dylib/plugin you could implement static C-like functions. What do they do? They initialize a new object of that new plugin subclass and return a pointer to the main app. That init routine is built into the plugin's dylib so it knows the specific name of that new class. But it returns a pointer to the main app of the base class type. And this will work because all the main app needs is a pointer to that new object. Then it'll interact with it using the generic member functions as defined in the base class. So the more robust you make that base plugin class, the more robust the new plugins people design can be.
 
Back
Top