Some applications may want to give the user the option to install third-party plugins that can extend the capabilities of the application. To achieve this in a nice way, the framework implements a light plugin loader interface that allows applications to load plugins in the form of shared libraries.

Note

As with all code binaries, the plugins need to be compiled individually for each platform and they may need to be compiled with the same version of the framework, as the application.

Warning

Due to limitations, enforced by Emscripten, module support is unavailable when targeting WASM.

Creating a plugin

Minimum requirements

A plugin is simply a shared library that exports the following 2 functions:

void UImGui_Plugin_attach(void* context);
void UImGui_Plugin_detach();

Warning

To export functions from C++, always wrap these 2 functions inside the following block:

#ifdef __cplusplus
extern "C"
{
#endif
// ...
#ifdef __cplusplus
}
#endif

This is required for the compiler to compile the functions as C symbols, rather than C++ symbols which go through have name mangling

Warning

To export functions from DLLs on Windows, you'll have to add __declspec(dllexport) in before the return type of the function to export it.

Loading the framework context

When creating plugins that interact with code provided by the framework, your plugin first needs to link to the larger framework library. Refer to here for the library model.

Next, in the UImGui_Plugin_attach function, you need to load the framework context before any other code that uses the framework runs. To do that, call the UImGui::Utility::loadContext function. This function's pointer arguments are 1:1 equivalent with the arguments that your UImGui_Plugin_attach function receives, with the exception that the attach function uses void* instead of the real types.

Users of the C API also have access to the UImGui_Utility_loadContext function which is identical.

Creating a plugin the proper way

The best way to create plugins is to use the create-plugin.sh script. Running the script, input the name of the plugin and the name of the project you want to extend. After that a directory with the name of the plugin, containing plugin.cpp and CMakeLists.txt files will be created under the Projects directory.

Caution

The project name you input should be available under Projects!

Listing standard plugins

A common aspect of adding plugin support to your application is setting a configuration file or directory from which plugins are loaded automatically.

We have decided to add this functionality to the uvproj.yaml file. Using this standard location for loading plugins makes development easier and also introduces a standard way for users to load plugins in multiple different applications.

The plugins are defined as string entries in the plugins array. Example uvproj.yaml file:

plugins:
  linux:
    - myplugin.so
    - myplugin2.so
  macos:
    - myplugin.dylib
    - myplugin2.dylib
  windows:
    - myplugin.dll
    - myplugin2.dll

The plugins interface

The Plugins interface defines functions that can be used to load the plugins. It looks like this:

class Plugins
{
public:
    Plugins() noexcept = default;

    static bool load(String location) noexcept;
    static const std::vector<Plugin>& getPlugins() noexcept;
    static void loadStandard() noexcept;

    ~Plugins() noexcept;
};

The functions do the following:

  1. load - manually loads a plugin from a plugin location as a string
  2. getPlugins - Returns the list of loaded plugins
  3. loadStandard - A helper function that loads all plugins defined in uvproj.yaml