IGUANA
Interactive Graphics for User ANAlysis - (Version 6.13.0.g4.81)
Guide > Developer > How to > Create a Plug-in
 

Valid XHTML 1.0 Transitional
Valid CSS!
Browser compatibility
tested on:
Opera/9.10
Firefox/1.5.0.7
Safari/2.0.4
IE/6.0.2900



 Overview

Plug-in packages differ from normal packages in that they must have an entry point to make the capabilities of the plug-in available to the IGUANA architecture. Usually -- but not always -- this also means that some extra information about the classes in the plug-in must also made be available. This is not strictly a feature of plug-ins, only most plug-ins will need to do so. A package should provide this additional information if the use of its classes with the IGUANA architecture requires it, whether or not that package is a plug-in. Therefore, you may need to follow this how-to even if you are not writing a plug-in. (The classes that must have this additional description are listed below.)
The additional information required by IGUANA architecture is the class inheritance structure of certain classes, provided using xtype_info fromIg_Imports/classlib in two parts: a declaration (the first step) and a definition (the second step). We do not yet have an automatic procedure for extracting this information for all classes, so we describe only the classes that absolutely need it. However,the classes that are described, must be described correctly. If the description is incorrect, the architecture will do most silly things; the problems are rather difficult to track. Therefore, please do not copy and paste code in these steps -- write it with thought.
In addition to providing the extended type information, plug-ins must define an entry point. The latter part of this how-to describes the steps to create the entry points, get the plug-in registered and to verify that it works as expected. All in all, the steps are as follows:
In this how-to we assume that you are creating a model package calledIgFooModel. We assume that your package has the classIgFooModel that inherits from the usual base classes in the architecture core (see the other how-to guides for more profound examples). We also assume it provides a service calledIgFooService that is somehow specific to the use of the model, and this service has two runtime-loaded extensions, IgFooBarExtension andIgFooBazExtension. Note that we also assume that you are using the IGUANA C++ templates (automatically available in our emacs customisation).

 Addinterface/xtypeinfo.h

In this step you willdeclare the extended type information for the classes that need to be descibed. The declaration should be public so that other packages can include it -- for example to further describe inherited classes. Our convention isinterface/xtypeinfo.h for the declaration andsrc/plugin.cc for the definition; follow these conventions also for packages that are not plug-ins.
The classes that must be described are those that participate in multi-methods: classes inheriting fromIgRepresentable, IgRep orIgModel. (This assuming only the multi-methods defined inIgObjectBrowser). You should describe the entire inheritance structure of the classes, so you may need to describe intermediate classes as well. If you the classes are already described in some other package, do not declare them in yours; just create a dependency on the other package (see the BuildFile step). If your classes inherit from external classes with large inheritance trees (such as Geant4 or Qt classes), and those intermediate classes are never used directly in extended type info mechanisms such as multi-methods, you are allowed to skip the externals in the description. Do note however that the description is completely outside the classes so it is perfectly possible to describe any external class.
Let us begin. Createinterface/xtypeinfo.h. It should include only two files: first theconfig.h of your package and then<classlib/xtypeinfo.h>. For each class that is to be described, first forward declare the class and then the extended type information withXTYPEINFO_DECLARE. Your header should now look like this:
#ifndef IG_FOO_MODEL_XTYPEINFO_H
# define IG_FOO_MODEL_XTYPEINFO_H

//<<<<<< INCLUDES                                   >>>>>>

# include "Ig_Modules/IgFooModel/interface/config.h"
# include <classlib/xtypeinfo.h>

//<<<<<< PUBLIC DEFINES                             >>>>>>
//<<<<<< PUBLIC CONSTANTS                           >>>>>>
//<<<<<< PUBLIC TYPES                               >>>>>>

class IgFooModel;

XTYPEINFO_DECLARE (IgFooModel);

//<<<<<< PUBLIC VARIABLES                           >>>>>>
//<<<<<< PUBLIC FUNCTIONS                           >>>>>>
//<<<<<< CLASS DECLARATIONS                         >>>>>>
//<<<<<< INLINE PUBLIC FUNCTIONS                    >>>>>>
//<<<<<< INLINE MEMBER FUNCTIONS                    >>>>>>

#endif // IG_FOO_MODEL_XTYPEINFO_H
				

 Add src/plugin.cc

In this step you will do two things: you will define the extended type information for the classes that were mentioned in the previous step, and define the plug-in description entry point. All this should go in src/plugin.cc.
First add the following includes:
  • Include the headers for all the classes declared in xtypeinfo.h (it is not necessary to include your config.h directly -- all your headers already include it).
  • Include your xtypeinfo.h.
  • Include xtypeinfo.h headers from all packages that define classes your classes inherit from.
  • Include IgObjectBrowser/interface/IgPluginDef.h.
Now, using XTYPEINFO_DEF macros in the "class structure initialisation" section, add type info definitions for the classes mentioned in xtypeinfo.h. There are several variants of the macro, depending on the number of base classes (0, 1, 2, 3 or 4). The first argument is the name of your class. Subsequent arguments are a pair of class name, inheritance type for each direct base class in the order they were specified in the class definition. The second argument of the pair should be true for virtual inheritance, false otherwise. The compiler must have seen a XTYPEINFO_DECLARE for every class named in XTYPEINFO_DEF -- hence you had to include xtypeinfo.h headers from all relevant packages above. If your package is not a plug-in but simply needs to provide extended type information, you are done; skip the rest of this how-to.
Next, in the "private types" section, declare a new class to describe your plug-in, named after your package -- for example IgFooModelPlugin for IgFooModel package. Inherit the class from IgPluginDef and add overrides for the query and attach methods. In the "class structure initialisation", introduce the plug-in registration entry point with DEFINE_IGUANA_PLUGIN; the macro takes as an argument the name of your plug-in class.
Finally, in the "member function definitions" section, define the query and attach methods. In query describe your plug-in using the IgPluginDef::declare* methods. In attach add factories for each entity declared in query, using the IgPluginDef::install* methods (capabilities do not need factories but you might need to add some other special code into attach). For any class that you install a factory for you will also need to include its header as well as the corresponding factory header from IgObjectBrowser (see the other how-to guides for specifics).
Your src/plugin.cc should now look like this:
//<<<<<< INCLUDES                                   >>>>>>

#include "Ig_Modules/IgFooModel/interface/IgFooModel.h"
#include "Ig_Modules/IgFooModel/interface/IgFooBarExtension.h"
#include "Ig_Modules/IgFooModel/interface/IgFooBazExtension.h"
#include "Ig_Modules/IgFooModel/interface/xtypeinfo.h"

#include "Ig_Framework/IgObjectBrowser/interface/IgPluginDef.h"
#include "Ig_Framework/IgObjectBrowser/interface/IgSimpleBrowserFactory.h"
#include "Ig_Framework/IgObjectBrowser/interface/IgSimpleExtensionFactory.h"
#include "Ig_Framework/IgObjectBrowser/interface/xtypeinfo.h"

//<<<<<< PRIVATE DEFINES                            >>>>>>
//<<<<<< PRIVATE CONSTANTS                          >>>>>>
//<<<<<< PRIVATE TYPES                              >>>>>>

class IgFooModelPlugin : public IgPluginDef
{
public:
	virtual void	query (void);
	virtual void	attach (void);
};

//<<<<<< PRIVATE VARIABLE DEFINITIONS               >>>>>>
//<<<<<< PUBLIC VARIABLE DEFINITIONS                >>>>>>
//<<<<<< CLASS STRUCTURE INITIALIZATION             >>>>>>

DEFINE_IGUANA_PLUGIN (IgFooModelPlugin);
XTYPEINFO_DEF_1 (IgFooModel, IgModel, false);

//<<<<<< PRIVATE FUNCTION DEFINITIONS               >>>>>>
//<<<<<< PUBLIC FUNCTION DEFINITIONS                >>>>>>
//<<<<<< MEMBER FUNCTION DEFINITIONS                >>>>>>

void
IgFooBrowserPlugin::query (void)
{
	declareExtension ("Runtime/Services/Foo/Bar");
	declareExtension ("Runtime/Services/Foo/Baz");
}

void
IgFooBrowserPlugin::attach (void)
{
	installExtension ("Runtime/Services/Foo/Bar",
			  new IgSimpleExtensionFactory
			  <IgFooBarExtension>);
	installExtension ("Runtime/Services/Foo/Baz",
			  new IgSimpleExtensionFactory
			  <IgFooBazExtension>);
}
				

 Modify BuildFile

Most of the work is now done. You still need to modify your SCRAM BuildFile to build and register your package as a plug-in. This consist of two steps: you must link your plug-in shared library against all other libraries it needs -- it cannot have any unresolved symbols -- and register it into your project's iguana-plugins database. Please refer first to the the corresponding section of the package creation how-to to see how we achieve this linking.
We augment the default receipe with a registration of the shared library created by the new package into the plug-in repository by including plugin_makefile.mk from the project's config directory ($(LOCALTOP)/$(projconfigdir)). In projects other than IGUANA this fragment causes shared libraries to be linked against their dependencies. In IGUANA this is the default and enabled for all packages.
Your BuildFile in the package root directory should now look like this:
<Use name=Ig_Framework/IgObjectBrowser>
<Use name=Ig_Extensions/IgQt>
<External ref=Qt>

<Export>
  <Lib name=IgFooBrowser>
</Export>

include $(LOCALTOP)/$(projconfigdir)/plugin_makefile.mk
				

 Build the package

You are now ready to build your plug-in with scram build. You should see your library linked against other libraries and the creation of an XML file in lib/archiguana-plugins. Note that in IGUANA your package must be mentioned in the build order to build it from the top level. See the new package how-to for the instructions.

Check the plug-in with iguana

Once your package has been built, verify that iguana can load the library and discover its properties. Running the following two commands should produce output that includes the entities from your plug-in:
$ eval `scram runtime -sh`
$ iguana --list
				
If you do not see the output you expected, turn on debugging:
$ env LOG=stderr: iguana --list
The debugging output will be verbose. Look for messages in the plugin-manager category saying "loading shared library". If there are problems with the library, this will be followed by a dynamic linker error message mentioning the first missing symbol. Common causes for errors include forgetting to link against some other library, forgetting to run moc (your package should have class libExamp in config/BuildFile), and forgetting to define one or more virtual functions.
You should also exercise the types defined in your library with debugging enabled as shown above. Look for messages in xtypeinfo category that say "inventing a xtype_info for an unknown type `...'". These will show up if you attempt to refer to xtype_info for types for which it was not defined (e.g. by applying a multi-method to an object when the real type of that object has no extended type info definition). You need to perform a proper test discover these, it is unusual for them to show up in mere plug-in registration.
Note
In projects other than IGUANA the $IGUANA_PLUGINS environment variable is currently not set correctly due to a SCRAM bug. After running scram runtime, make sure the variable includes the following directories, in this order: lib/arch/iguana-plugins in your project area, then in your base release, then in IGUANA release.