Basics Of Plugins
English 简体中文
By Girish Ramakrishnan, ForwardBias Technologies
Plugin overview
Plugins are a mechanism of extending existing programs. As an example, a Calculator program can extend it’s list of supported operations by loading additional operators from plugins. Plugins allow third party developers to extend the calculator program without requiring access to the calculator program source code.
Creating plugins
In C, plugins are created using the following steps:
- The application defines an interface for plugins. These are a list of functions that the application expects to be implemented by a plugin.
- A plugin implements the interface and the code is compiled as a shared object.
- The application discovers the plugin, dynamically loads the plugin, resolves the symbols/functions in the plugin and calls the methods defined in the interface.
Let’s take the example of a Calculator program that can be extended using plugins.
- The Calculator program defines the interface as:
- The ‘addition’ plugin implements the interface as
The plugin is compiled as a shared object using ‘cc -shared -fPIC addition.c -o addition.so’.
- The Application discovers plugins at runtime by searching preconfigured paths for shared objects.
Exporting symbols in C
A shared object may contain many functions but only some of them are meant to be exposed to external programs. Compilers provide mechanisms to mark the visibility of functions. In gcc, this is achieved by prefixing attribute((visibility(“default”))). On MSVC, __declspec(dllexport) is prefixed to a function or a class.
The addition plugin should be written as:
Exporting symbols in C++
In C, the mapping of names to symbols in standardized. C++, however, has no such standard and each compiler generates different symbol names for the same function name. This name mangling is required to support C++ function overloading, wherein many functions can have the same name but different signature.
Thus, in C++,
- The resolving of the symbol “operation” using dlsym, as in the example above, will fail if the plugin was compiled using a C++ compiler. The programmer will need to resolve the mangled name instead.
- Resolving on mangled names is compiler dependent. If the plugin was compiled using a different compiler then even resolving using the mangled name will not work.
The trick to solve the above problems is to define the interface in C++ but have a single C function that returns a pointer to the interface. This C function is compiled using C-linkage (specified using extern “C”). For example, the above plugin can be implemented as C++ as follows: