Plugins are objects that are loaded during runtime from dynamic libraries.
Cornerstone supports two types of plugins: Widget plugins and Operator plugins. Cornerstone will search for plugins in certain directories (see Plugin Locations) when it starts.
Typically the work when writing new code is pretty much identical to comparing writing an application as a stand-alone binary or a plugin. The benefits of plugins are that they can later be embedded into other applications easily. The plugin system provides automatic factory construct to instantiate plugins by their name. The plugin system is also used to implement serialization in Cornerstone.
There are a few basic rules that should be taken into account when designing a class to work as a plugin. First, it must have a default constructor. Second, ideally the (widget) plugin never assumes or references anything outside the widget hierarchy that it creates by itself. Basically, make no assumptions of the widget hierarchy outside the plugin. This makes it easy to re-use and embed the plugin in future applications.
To make a widget plugin, create a custom widget with a default constructor and use the WIDGET_PLUGIN macro.
The WIDGET_PLUGIN macro will create the necessary factory objects so it can be instantiated with MultiWidgets::createPlugin function.
To create operator plugins, just inherit from MultiWidgets::Operator and use the OPERATOR_PLUGIN macro instead.
Plugins can be compiled and linked statically to applications and they will work. However, if you want to make your plugin load during runtime from a dynamic library there are few things that must followed.
The plugin filename and path must be of the following form:
MissileCmd.cswidget/2.0.0-rc2/MissileCmd.{dll|dylib|so}
The plugin must be located in the directory structure where the top level directory is the name of the plugin with suffix (.cswidget). Second level directory is the version string of Cornerstone SDK (2.0.0-rc2) that the plugin is compiled with. Only plugins that have the same Version than Cornerstone will be loaded. The library file itself has to have platform's canonical extension for dynamic libraries for it to be loaded.
If the file is not named correctly, the plugin framework will not register it. To make this easy for the user, Cornerstone SDK ships with a project template file called plugin.pri including this file in a qmake project file will automatically set the correct build options for building a plugin and will build it to the directory that has correct structure.
NOTE: On Windows, for DEBUG builds the plugin filename must also include _d. For example:
MissileCmd.cswidget/2.0.0/MissileCmd_d.dll
This is to prevent accidental mixing of different runtimes in debug and release builds on Visual Studio. Other platforms do not need this separation of debug/release builds. The debug builds of the applications use debug-versions of plugins. Pre-compiled applications (most notably ScriptRunner and MultiPluginDriver) shipped along Cornerstone are release builds so they do not support debug plugins.
Plugins must be placed into correct location on the filesystem so that Cornerstone can find them. If multiple plugins with the same id are found, only the first instance is loaded.
Plugins are searched for in the following directories in order:
First, Cornerstone checks for the CORNERSTONE_PLUGIN_DIR environment variable. It can contain a list of paths separated by semicolon (;).
Second, the default plugins are loaded from CORNERSTONE_SDK_ROOT/lib/plugins.
Finally, plugins are loaded from the the platform-specific folder under the user's home directory: