Writing plug-ins for Gyoto

Al the generic Gyoto machinery for computing orbits, reading input files, performing ray-tracing etc. is implemented in libgyoto. On the other hand, all the code specific to a given metric kind or a given astronomical object is available in plug-ins. For instance, the standard plug-in libgyoto-stdplug contains the two flavors of the Kerr metric: Gyoto::KerrBL and Gyoto::KerrKS, as well as basic objects: Gyoto::FixedStar, Gyoto::Star, Gyoto::Torus, Gyoto::ThinInfiniteDiskBL and Gyoto::ThinInfiniteDiskKS. The libgyoto-lorene plug-in contains the code to access numerical metrics (Gyoto::LoreneMetric) as well as an example thereof: Gyoto::RotStar3_1. The two basic spectral shapes Gyoto::Spectrum::PowerLaw and Gyoto::Spectrum::BlackBody are also to be found in the standard plug-in.

Gyoto can be used right away to compute stellar orbits in the Kerr metric or to do basic ray-tracing of accretion disks. But Gyoto is not limited to the basic metrics and objects we have thought of. It is fairly easy to add custom metrics and objects (and emission/absorption laws) it Gyoto, and Gyoto itself does not need to be modified or even re-compiled to do so: custom classes can (and should) be implemented as plug-ins. For an example, simply look at the lib/StdPlug.C file in the source distribution, and the source files for the objects and metrics it provides: e.g. lib/FixedStar.C and lib/KerrBL.C.

To implement a new plug-in, you first need to implement a derived class of either the Gyoto::Astrobj, Gyoto::Metric, or Gyoto::Spectrum::Generic class. You don't necessarily need to implement everything, the Gyoto::Astrobj page explains what is required for an astronomical object.

Assuming you want to be able to actually use your custom class, you need a way to instantiate it. This is normally the job of the Gyoto::Factory. You need to instruct the Gyoto::Factory how to read parameters for your specific class from an XML file by implementing a subcontractor (for a Gyoto::Astrobj, the subcontractor is a static method of the Gyoto::Astrobj::Subcontractor_t type). The subcontractor communicates with the Gyoto::Factory by means of a Gyoto::FactoryMessenger and basically loops calling the Gyoto::FactoryMessenger::getNextParameter() method (see the GyotoRegister.h file, unfortunately undocumented at the moment).

You also need to register your subcontractor, so that the Gyoto::Factory knows it must call it when it encounters a tag of the form <Astrobj kind="YourKind"> in an XML description. This is typically done by providing an static Init method in your class:

void Gyoto::FixedStar::Init() {
Gyoto::Astrobj::Register("FixedStar", &Gyoto::FixedStar::Subcontractor);
}
Gyoto::Astrobj::Register
void Register(std::string name, Gyoto::Astrobj::Subcontractor_t *scp)
Make an Astrobj kind known to the Factory.

You need to make sure this Init() method is called when your plug-in is loaded. Assume you decide to call your plug-in MyPlug, and it contains a single Gyoto::Astrobj named Gyoto::MyObj. You will compile it under the file name libgyoto-MyPlug.so (under Linux) or libgyoto-MyPlug.dylib (under MacOS X). Just put this file somewhere where the dynamic linker can find it (any directory listed in $LD_LIBRARY_PATH or $DYLD_LIBRARY_PATH will be fine; /usr/local/lib/ should also be fine). In addition to the implementation of the Gyoto::MyObj class, you will need to provide a function called __GyotoMyPlugInit() which will be exactly this:

extern "C" void __GyotostdplugInit() {
Gyoto::MyObj::Init();
}

This function is typically provided in a separate source file (such as lib/StdPlug.C in the Gyoto source) and can initialize several custom classes at once.

Finally, you need to instruct Gyoto to load your plug-in at run time. This is done by adding the name of your plug-in to the GYOTO_PLUGINS environment variable. The default value for GYOTO_PLUGINS is "stdplug,nofail:lorene", meaning Gyoto should load the standard plug-in stdplug and attempt to load the lorene plug-in, failing only if stdplug is nowhere to be found. If you want to load your plug-in in addition to those, alter this variable in your shell (if you don't know what this means or how to do this, ask the local Unix guru or read the fine manual):

export GYOTO_PLUGINS="stdplug,nofail:lorene,MyPlug"

but if your lug-in is self-contained and your don't need the objects in the standard plug-ins, this will do it for you:

export GYOTO_PLUGINS="MyPlug"

This will instruct Gyoto to locate and load the file named libgyoto-MyPlug.(so|dylib) and to run the function named __GyotostdplugInit() from this library file.