Plugin Lifecycle

Coraline plugins are dynamically linked shared object libraries (.so files).  This has three consequences:

  1. They don’t have to (though they can) be distributed with the apps: one shared installation is good enough for any apps that require it.
  2. They need some standard functions present to be able to be loaded.
  3. They need to provide some instance that implements the Coraline Plugin interface.

The skeleton code generator handles this minutiae, and its code creates plugins based on a helper class that handles a lot of the boilerplate and gives some utility function, but it’s all documented here nonetheless.

The plugin lifecycle is essentially:

dlopen library
  supports_driver()
  create_object()
    plugin registration
    plugin JS injection
    plugin startup
       updates/plugin callbacks
    plugin shutdown
  destroy_object()
dlclose libray

Pre initialization

Dynamically loadable libraries containing coraline plugins are first

  1. opened;
  2. checked for all the mandatory loader functions
  3. checked for a “true” return from the libaries supports_driver(), called with the running version of Coraline

If any of these checks fails, the library is closed and subsequently ignored.

Instantiation

Plugin instances are created, by Coraline at startup, and created using the library’s create_object().

If the plugin is not required by the app, it will then be released/destroyed using its destroy_object(). The end.

Registration

If is required by the app, it is given a chance to initialize and register with the system plugin registry. When using Plugin::Base, (as in the code created by the generator) this process is simplified a bit, and you need only override registerAllMethods() in order to make your callbacks visible to the system (e.g. with the PLUGINREGMETH() macro).

JS Injection

As the final step of instantiation, the plugin is given a chance to inject
“driver” javascript code into the JS engine.

This can be done a few ways, the simplest being to override Plugin::Base‘s

  • clientSideSupportFile() (just return a JS filename to load from
    under shortName() directory); or
  • clientSideSupport() (return a string of JS to eval in the JS engine)

 

Start Up

Once all the required plugins have been instantiated, as described above, the start-up signal is given, and each loaded plugin will get one call to it’s startUp() method.

Device Ready

After all plugins have started up, the device ready signal is given to client code, and you can expect callbacks to be triggered at any time.

Running

While running, your plugin’s update() method will be periodically ticked.  If you’re basing your plugin on the Plugin::Base helper, you don’t actually have to manage this–it’ll take care of any actions queued using queueAction().

You will also have callback methods triggered by the client app, as requested by that side.

The simplest approach is to inherit from Plugin::Base and have
your callbacks queue UpdateActions (which are just void(void) lambdas, using queueAction()) to report information/success/failure.

These will actions be executed on the next update().

Your job, while running, is to keep things snappy so the UI remains responsive.

Process any long operations in the background and, ideally, trigger
the JS-side callbacks during a subsequent update() using the UpdateActions queue.

Shutdown

Prior to unloading a plugin, it’s shutdown() method will be called to give you a chance to do any required clean up.

Destruction

The final step before closing the library will be a call to destroy_object(), passing in the plugin instance.