add preliminary documentation for plugin command and about how to write plugins
This commit is contained in:
98
doc/src/Developer_plugins.rst
Normal file
98
doc/src/Developer_plugins.rst
Normal file
@ -0,0 +1,98 @@
|
||||
Writing plugins
|
||||
---------------
|
||||
|
||||
Plugins provide a mechanism to add functionality to a LAMMPS executable
|
||||
without recompiling LAMMPS. This uses the operating system's
|
||||
capability to load dynamic shared object (DSO) files in a way similar
|
||||
shared libraries and then references specific functions those DSOs.
|
||||
Any DSO file with plugins has to include an initialization function
|
||||
with a specific name that has to follow specific rules. When loading
|
||||
the DSO, this function is called and will then register the contained
|
||||
plugin(s) with LAMMPS.
|
||||
|
||||
From the programmer perspective this can work because of the object
|
||||
oriented design where all pair style commands are derived from the class
|
||||
Pair, all fix style commands from the class Fix and so on and only
|
||||
functions from those base classes are called directly. When a
|
||||
:doc:`pair_style` command or :doc:`fix` command is issued a new
|
||||
instance of such a derived class is created. This is done by a
|
||||
so-called factory function which is mapped to the style name. Thus
|
||||
when, for example, the LAMMPS processes the command
|
||||
``pair_style lj/cut 2.5``, LAMMPS will look up the factory function
|
||||
for creating the ``PairLJCut`` class and then execute it. The return
|
||||
value of that function is a ``Pair *`` pointer and the pointer will
|
||||
be assigned to the location for the currently active pair style.
|
||||
|
||||
A plugin thus has to implement such a factory function and register it
|
||||
with LAMMPS so that it gets added to the map of available styles of
|
||||
the given category. To register a plugin with LAMMPS an initialization
|
||||
function has to be called that follows specific rules explained below.
|
||||
|
||||
|
||||
As an example, for a hypothetical pair style "morse2" implemented in a
|
||||
class ``PairMorse2`` in the files ``pair_morse2.h`` and
|
||||
``pair_morse2.cpp`` the file with the factory function and initialization
|
||||
function would look like this:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
#include "lammpsplugin.h"
|
||||
#include "version.h"
|
||||
#include "pair_morse2.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
static Pair *morse2creator(LAMMPS *lmp)
|
||||
{
|
||||
return new PairMorse2(lmp);
|
||||
}
|
||||
|
||||
extern "C" void lammpsplugin_init(void *lmp, void *handle, void *regfunc)
|
||||
{
|
||||
lammpsplugin_regfunc register_plugin = (lammpsplugin_regfunc) regfunc;
|
||||
lammpsplugin_t plugin;
|
||||
|
||||
plugin.version = LAMMPS_VERSION;
|
||||
plugin.style = "pair";
|
||||
plugin.name = "morse2";
|
||||
plugin.info = "Morse2 variant pair style v1.0";
|
||||
plugin.author = "Axel Kohlmeyer (akohlmey@gmail.com)";
|
||||
plugin.creator = (lammpsplugin_factory *) &morse2creator;
|
||||
plugin.handle = handle;
|
||||
(*register_plugin)(&plugin,lmp);
|
||||
}
|
||||
|
||||
The factory function in this example is called ``morse2creator()``. It
|
||||
receives a pointer to the LAMMPS class as argument and returns a
|
||||
pointer to the allocated class instance derived from the ``Pair`` class.
|
||||
This function may be declared static to avoid clashes with other plugins.
|
||||
The name of the derived class, ``PairMorse2``, must be unique inside
|
||||
the entire LAMMPS executable.
|
||||
|
||||
The initialization function **must** be called ``lammpsplugin_init``, it
|
||||
**must** have C bindings and it takes three void pointers as arguments.
|
||||
The first is a pointer to the LAMMPS class that calls it and it needs to
|
||||
be passed to the registration function. The second argument is a
|
||||
pointer to the internal handle of the DSO file, this needs to added to
|
||||
the plugin info struct, so that the DSO can be close and unloaded when
|
||||
all its contained plugins are unloaded. The third argument is a
|
||||
function pointer to the registration function and needs to be stored
|
||||
in a variable of ``lammpsplugin_regfunc`` type.
|
||||
|
||||
To register a plugin a struct of the ``lammpsplugin_t`` needs to be filled
|
||||
with relevant info: current LAMMPS version string, kind of style, name of
|
||||
style, info string, author string, pointer to factory function, DSO handle.
|
||||
The the registration function is called with a pointer to the address of
|
||||
this struct and the pointer of the LAMMPS class. The registration function
|
||||
will then add the factory function of the plugin style to the respective
|
||||
style map under the provided name. It will also make a copy of the struct
|
||||
in a list of all loaded plugins and update the reference counter for loaded
|
||||
plugins from this specific DSO file.
|
||||
|
||||
The pair style itself (i.e. the PairMorse2 class in this example) can be
|
||||
written just like any other pair style that is included in LAMMPS. For
|
||||
a plugin, the use of the ``PairStyle`` macro in the section encapsulated
|
||||
by ``#ifdef PAIR_CLASS`` is not needed, since the mapping of the class
|
||||
name to the style name is done by the plugin registration function with
|
||||
the information from the ``lammpsplugin_t`` struct. It may be included
|
||||
in case the new code is intended to be later included in LAMMPS directly.
|
||||
Reference in New Issue
Block a user