Elm
1.0
ELM is a library providing generic data structures, OS-independent interface, plugins and XML.
|
Classes | |
class | elm::sys::Plugger |
class | elm::sys::Plugin |
ELM provides classes to implement plugins in an OS-indepedent way. To work-around found on some OS, ELM provides also an independent way to optionaly represent dependencies between plugins based on textual file with ".ini" syntax.
A plugin is a piece of code that provides some service while the plugger allows to plug many different plugins to implement this service.
In ELM, the plugger is declared with a hook - an identifier allowing an application to have different kinds of services and matching plugins - and a version for the current implemented plugin interface. For example, below, the plugger provides "net_plugin" services at version 1.0.0 (see elm::Version for more details). We may also gives a list of directories to look to find the plugin.
To open a specific plugin named, for example, "my_net_plugin", we have only to call the method Plugger::plug().
If the plugin is found, is loadable and has a compatible version, it is loaded, initialized and its instance is returned. If there is an error, a null pointer is returned and the method Plugger::lastErrorMessage() may give some information about the error.
Having just a plugin pointer does not provide any service. To do this, we have usually to define an interface that is implemented by the plugin instance. Let's call it "NetPlugin": it must be derived from the elm::system::Plugin class. Notice that the interface pass the right name of the service but should not pass the version. Otherwise, the service version would be ever compatible while the actual binary would be compiled for an incompatible version.
Then, we can cast the plugin to its required interface and we can call the service:
When the plugin is no more needed, we can simply unplug it:
To create a plugin, we have to define a class implementing the service interface of the plugger to plug to. Let's continue the example started in the previous section. Notice that we must implement the pure virtual functions of the interface in order to be able to create an instance of the plugin class.
Then, the constructor must pass to the elm::system::Plugin class the name of the service to be hooked to the right plugger with the service version supported by the plugin.
Notice how the version is encoded in the plugin code. If this plugin is then used with in incompatible version of the plugger, say 1.2.0. The compatibility comparison will compare the version 1.0.0 (from the plugin) with the version 1.2.0 (from the plugger) and will detect possible binary incompatibility and prevent the invalid linkage.
Then we need to provide a hook to let the plugger found the plugin object.
The result source must then be compiled to produce a shared code with your preferred compiler For example, with GCC on a Unix OS.
ELM Linkage Description (ELD) files allows to circumvent limitations found on some OSes. Basically, ELD files are textual files with ".eld" extension implementing the ".ini" file syntax. They must placed in the same directory as the plugin they apply to and get the same name as the plugin with the plugin extension replaced by ".eld".
As usual ".ini" files, they can contain as many sections as possible but ELM is only interested in the "elm-plugin" section that may contain the following definitions:
"path" definition allows to cope with the lack of support for symnolic links on some OSes.
"rpaths" and "libs" are used to handle easily dependencies between plugins and libraries when the OSes does not support linkage lookup path encoded in executable.
Paths found in "path", "libs" and "rpaths" can be prefixed by "$ORIGIN" that is replaced, at run time, by the path of the directory containing the considered plugin.
Below is an example of ELD files for our example requiring two other libraries that should be found in the directory containing the plugin or in directory "/usr/lib". It is named "net_plugin.eld" and put in the same directory as "net_plugin.so".
Below another example allows to have an alias, "net_plugin_v2" to "net_plugin". The file is named "net_plugin_v2.eld":
This last example links with library libxml2 from the OS path:
The old-style plugin creation remains supported but is marked as deprecated.
Here, the plugin of the example must be declared with:
Notice how description and license were passed in the constructor.
The second difference stands in the way to declare the hook (it has proven to no robust enough):