Feature guide » Loading and using plugins

Extending Magnum with additional functionality.

The base Magnum library contains math support, scene graph implementation and is able to interact with graphics and audio hardware. However, the base library doesn't provide any functions for dealing with specific file formats, as there are simply too many formats to have them included directly in the library. Instead, the library provides plugin API and you can load plugin which will then be able to read or write the particular file format.

The Magnum repository contains a few basic plugins for opening the some formats, such as TGA images or WAV audio files. These plugins are included because the file formats are so simple that no external library is needed for loading their contents and thus they are suitable for quick demos and prototyping without dealing with additional dependencies.

Additional plugins (such as importers for PNG and JPEG images, FreeType fonts etc.) are available in Magnum Plugins repository. Majority of these plugins depends on external libraries, thus some of them might not be available on all platforms.

Plugin interfaces

Magnum contains these plugin interfaces:

  • Trade::AbstractImporter — importers for general 2D and 3D scene, mesh, material, texture and image data. See *Importer classes in Trade namespace for available importer plugins. These are installed in MAGNUM_PLUGINS_IMPORTER_DIR directory.
  • Trade::AbstractImageConverter — conversion among various image formats. See *ImageConverter classes in Trade namespace for list of available image converter plugins. These are installed in MAGNUM_PLUGINS_IMAGECONVERTER_DIR directory.
  • Text::AbstractFont — font loading and glyph layouting. See *Font classes in Text namespace for available font plugins. These are installed in MAGNUM_PLUGINS_FONT_DIR directory.
  • Text::AbstractFontConverter — font and glyph cache conversion. See *FontConverter classes in Text namespace for available font converter plugins. These are installed in MAGNUM_PLUGINS_FONTCONVERTER_DIR directory.
  • Audio::AbstractImporter — importers for audio formats. See *Importer classes in Audio namespace for available audio importer plugins. These are installed in MAGNUM_PLUGINS_AUDIOIMPORTER_DIR directory.

Loading and instantiating the plugins

To load the plugins, you need to instantiate Corrade::PluginManager::Manager for given plugin interface, for example Trade::AbstractImporter. You must set particular plugin directory, from which the manager will load and instantiate the plugins. To save you from hardcoding the value into your application source, the plugin directory is provided as MAGNUM_PLUGINS_DIR CMake variable. The default is set to Magnum install location, but you can change it through CMake to anything else. The MAGNUM_PLUGINS_IMPORTER_DIR, MAGNUM_PLUGINS_IMAGECONVERTER_DIR, MAGNUM_PLUGINS_FONT_DIR, MAGNUM_PLUGINS_FONTCONVERTER_DIR, MAGNUM_PLUGINS_AUDIOIMPORTER_DIR variables depend on MAGNUM_PLUGINS_DIR, so if you modify that variable, the changes will be reflected in these variables too. See Usage with CMake for additional information.

You can provide the variable to your sources using CMake configuration file. Create configure.h.cmake file in your source directory with contents similar to these:


In case you are using multi-configuration build system (such as Visual Studio or XCode), CMake cannot provide separate plugin directory for debug and release build and you have to select between MAGNUM_PLUGINS_*_DIR and MAGNUM_PLUGINS_*_DEBUG_DIR based on CORRADE_IS_DEBUG_BUILD preprocessor variable. This will ensure that you use debug plugin directory for debug build on multi-configuration build sytems and fall back to autodetection for the rest:


However, if you want to use only one (debug/release) plugin version for both debug and release configurations of the application, you need to edit MAGNUM_PLUGINS_DIR or MAGNUM_PLUGINS_DEBUG_DIR using CMake and point them to directory containing desired plugin version.

Then process the file in your CMakeLists.txt. The result (${MAGNUM_PLUGINS_IMPORTER_DIR} / ${MAGNUM_PLUGINS_IMPORTER_DEBUG_DIR} gets replaced with the actual value) is put into build directory, so don't forget to add it to include path:


Then you can instantiate the manager, load particular plugin and create an instance of it. Keep in mind that the manager instance must exist for whole lifetime of all plugin instances created from it.

#include "configure.h"

// ...

    PluginManager::Manager<Trade::AbstractImporter> manager{MAGNUM_PLUGINS_IMPORTER_DIR};
    std::unique_ptr<Trade::AbstractImporter> tgaImporter = manager.loadAndInstantiate("TgaImporter");
    if(!tgaImporter) {
        Error() << "Cannot load importer plugin from" << manager.pluginDirectory();

    // Use the plugin...

    // At the end of the scope the tgaImporter instance gets deleted and then
    // the manager automatically unloads the plugin on destruction

Plugin dependencies

Some plugins have dependencies, for example the MagnumFont plugin needs to load the glyph atlas using TgaImporter plugin. The dependency loading is done automatically, but you need to create instance of corresponding plugin manager in particular plugin dir so the dependency can be found. Example:

PluginManager::Manager<Trade::AbstractImporter> importerManager(MAGNUM_PLUGINS_IMPORTER_DIR);
PluginManager::Manager<Text::AbstractFont> fontManager(MAGNUM_PLUGINS_FONT_DIR);

// As a side effect TgaImporter is loaded by importerManager

Static plugins

By default all plugins are built as dynamic ones, i.e. they are separate binary which gets linked in at runtime. This is good for reducing memory consumption, as the code is loaded in memory only for the time it is needed. However, if you want to port to platform which does not support dynamic linking or you simply want to have the plugin loaded at all times, you can use static plugins.

The plugins are built as static if BUILD_STATIC CMake parameter is enabled (see Downloading and building and Downloading and building plugins for more information). The actual usage is basically the same as above, but you need to explicitly find the plugin and link it into the executable in your CMakeLists.txt. See Usage with CMake and Plugin usage with CMake for additional information.

find_package(MagnumPlugins REQUIRED PngImporter)

add_executable(MyApp ...)
target_link_libraries(MyApp ... MagnumPlugins::PngImporter)

The only user-visible behavioral change will be that PluginManager::Manager::load() will return PluginManager::LoadState::Static instead of PluginManager::LoadState::Loaded, but there is no need to change the above code, as it will work for both dynamic and static case.

It's needed to register the static plugin with CORRADE_PLUGIN_IMPORT() in some function which will be executed before you use the plugin, otherwise the plugin will not be found. See the macro documentation for information about automatic importing and namespace issues.

int main(int argc, char** argv) {

    // ...

Developing your own plugins

See class documentation of particular plugin interfaces for more information about subclassing. The Corrade's plugin management tutorial contains more information about plugin compilation and registering.

If you want to develop a plugin which depends on another, you need to find the original plugin, add its include dirs to include path and link to it, similarly to how static plugins are found above. See Usage with CMake and Plugin usage with CMake for more information.