The way modules building is explained here is not the one explained in the "standard" IRIS Explorer manuals. But we found easier the method explained here even if there is less "mouse interactions" and more typing.
An Explorer module has two main aspects:
This document is a "step by step" modules creation guide. It shows all the various tasks you should perform in order to build a module. First we will see how to build a very simple module with no parameters (ports). Then we will increase the complexity by adding input and output ports to the module. This will be done using the modules adapters developed at CERN.
the program will display the following window:

Just click on "OK" . Now one window called Module Builder remains on the screen. Only the field Module name is not empty. It should contain the string modulename.


A panel, called Build Options, will pop up in which you should define:

The other fields of the panel should not be changed. Then press
in this panel.
Now the only window on the screen is the Module Builder.
The Functions Args panel will pop up.
In this panel we shall define the name of the function which will be executed each time the module will be fired: in the Func Name field you should enter the name of the function, for example moduleName.
We will work in C++ language so the Language should be set on C++.
The top of the Function Args panel should now looks like:
The other fields of the panel should not be changed. You can now press
in this panel.

This action will display the Hook Functions panel. All the fields in this panel are empty. You should enter the string initHook in the Init Hook Function field, and the string removeHook in the Remove Hook Function field. The Hook Functions panel should now looks like:

Now you can press
in this
panel. The only window on the screen is now the Module
Builder.
The mbuilder phase is now finished. The next step is the definition of the code executed in the module. Before exiting the Module Builder, you should save your work by selecting the Save resources item of the File menu in the Module Builder window:

When the saving is done, you can exit the Module Builder by selecting the Quit item in the File menu:

#include <stdio.h>
extern "C" {
void moduleName ( void );
void initHook ( void );
void removeHook ( void );
}
//-----------------------------------------------------------------------------
//
// This function is the kernel of the module.
//
void moduleName (void) {
printf ("moduleName is called \n");
}
//-----------------------------------------------------------------------------
//
// Hook function for Explorer module actions.
// This function is executed once when the module start.
//
void initHook(void)
{
printf ("initHook is called \n");
}
//-----------------------------------------------------------------------------
//
// Hook function for Explorer module actions.
// This function is executed when the module stop.
//
void removeHook(void)
{
printf ("removeHook is called \n");
}
$ cxmkmf
Then the module executable should be created. For that just type:
$ make
$ explorer
You should find your module in the Librarian on Localhost window. Just type mod in the Modules scroll list and you should see your module as follow:

To test the module, you should create a instance of it in the Map
Editor window by "drag-and-droping" with the left mouse button
the box
in the Map
Editor window as shown in the following figure:

This module does nothing for the time being. But with the printf(s) we put in the modulename.cpp file we can check that the functions moduleName, initHook and removeHook are called and executed correctly.
We can check immediately that the initHook function has been called. This function is called when the module in put in the Map Editor. We can see that initHook has been called by looking in the Explorer Log window:

To check that the function moduleName is working, you should "fire" the module. This can be done using the pull down menu available when you click on the right mouse button on the module name in the module box. When the menu appears choose the item Fire Now. The Explorer Log window contains now:

The function removeHook is called when the module is destroyed. To destroy the module just select the Destroy item in the same pull down menu we used before to fire the module. You can also "drag and drop" the module box on the Destroy icon:
The Explorer Log window should now looks like (??) :

We have now seen the complete module creation chain: from the module builder phase to the module execution. We will now see how to add parameters to the module.
As we already said we will use the adapters build at CERN. With this method the calling sequence of the module "core function" (moduleName) remains unchanged (i.e. : void), whatever the number of module parameters is.

The modulename.mk file allows to customize the Makefile generated from the resources file. For that a set of environment variables is provided. These variables are used by the Makefile and by defaults are not defined. As we assumed we are working in C++, the variables we will use are the following:
| Variable | Meaning |
|---|---|
| DEFINES | Definitions for cpp use in C++ compiles, and in make depend |
| C++DEFINES | Passed to the C++ compiler |
| INCLUDES | Include directory specification for cpp use in C++ and in make depend |
| C++INCLUDES | Includes directory specification for cpp use in C++ compiles |
| LOCAL_LDFLAGS | Loader flags to be passed when linking modules |
| LOCAL_LIBRARIES | Library filenames relative to the local directory (or fully qualified). Used in linking modules and in calculating dependencies so that the module will re-link if any of these libraries changes. |
| SYS_LIBRARIES | System libraries (given in the -L<dir> -l<lib> form) to be passed to the loader. |
| EXTRA_LIBRARIES | User libraries (given in the -L<dir> -l<lib> form) to be passed to the loader. |
C++INCLUDES = -I/afs/cern.ch/sw/lhcxx/specific/@sys/HEPEXPLORER/pro/include/ \ -I$(EXPLORERHOME)/include -I$(EXPLORERUSERHOME)/include EXTRA_LIBRARIES = -L/afs/cern.ch/sw/lhcxx/specific/@sys/HEPEXPLORER/pro/lib/ \ -lHEAdaptors $(C++INCLUDES)
Then defined these parameters as Optional with the menus choices on the right of the Input Ports window.
The parameters type are not changed and are defined as cxParameter. The Input Ports window should now looks like:

Now you can click on the button
to validate the changes.


To define the graphical user interface of one parameter just click on the parameter name you want to work on. All the current attributes values of the selected parameter will be displayed in the Control panel Editor and can be edited.
In this example ParInput will stay as a pure input parameter (input port) with no user interface. This parameter will be changed only via input values coming from the output ports of other modules.
On the other hand, Dial will be connected to a Dial widget. To do that it is enough to define the Type of the Widgets Attributes. In the Type menu choice select Dial. The preview of the module graphical user interface is now:

The appearance of the module graphical user interface can now be changed in a WYSIWYG way just using the mouse. You can change the size of the window, adjust the widget position in the window etc. ...
The limits in which varies the parameter and its initial value can be changed by clicking (once) in the corresponding text field and by typing the new value in place.
Some extra widget properties can be also defined by double clicking on the widget itself. The extra properties are displayed in the Control Panel Editor.
Having done all these manipulations you can get something like:

The corresponding Control Panel Editor window being:

Now you can click
in the Control
Panel Editor window.
When you have finished the Output Ports window should looks like:

Now you can click on the button
to validate the changes.
To validate all the changes (for input and output parameters), you should save the resources and quit the module builder as we already explained before.
Then you can build a new version of the module.
The code in the file modulename.cpp should be changed. The new version is:
#include "HEAdaptors/HEInputParam.h"
#include "HEAdaptors/HEOutputParam.h"
extern "C" {
void moduleName ( void );
void initHook ( void );
void removeHook ( void );
}
static HEInParamLong *parinput;
static HEInParamLong *dial;
static HEOutParamLong *paroutput;
//-----------------------------------------------------------------------------
//
// This function is the kernel of the module.
//
void moduleName (void) {
if (dial->lookUp() || parinput->lookUp()) {
long ParInputValue;
long DialValue;
ParInputValue = parinput->getValue();
DialValue = dial->getValue();
paroutput->setValue(ParInputValue*DialValue);
paroutput->sendOut();
}
}
//-----------------------------------------------------------------------------
//
// Hook function for Explorer module actions.
// This function is executed once when the module start.
//
void initHook(void)
{
parinput = new HEInParamLong("ParInput");
dial = new HEInParamLong("Dial");
paroutput = new HEOutParamLong("ParOutput");
}
//-----------------------------------------------------------------------------
//
// Hook function for Explorer module actions.
// This function is executed when the module stop.
//
void removeHook(void)
{
delete parinput;
delete dial;
delete paroutput;
}
The modifications compared to the previous
version are paint in green.
Three adapters are declared as static pointers at the beginning of the file.
In initHook the adapters are created. At creation time, each adapter constructor has one parameter: the name of the parameter. This name should be exactly the same as the one given in the module builder.
The adapters are deleted in removeHook.
In the moduleName function:

With this new version of modulename you can move the dial in the module graphical user interface or change the value in PrintParam and you will see the value changing in PrintParam<2>.
The Module Builder window should be:

Where HistOOgramRename.mk is:
OTH_INC = -I/afs/cern.ch/sw/lhcxx/specific/@sys/HEPEXPLORER/pro/include/ \ -I$(EXPLORERHOME)/include -I$(EXPLORERUSERHOME)/include HISTOO_INC = -I$(HISTOODIR)/code OBJY_INC = -I$(OBJY_DIR)/include HEP_ODBMS_INC = -I$(HEP_ODBMS_DIR)/include C++INCLUDES = $(OTH_INC) $(HISTOO_INC) $(OBJY_INC) $(HEP_ODBMS_INC) OTHLIB = -L/afs/cern.ch/sw/lhcxx/specific/@sys/HEPEXPLORER/pro/lib/ \ -lHEAdaptors $(C++INCLUDES) HISTO_LIB = -L$(HISTOODIR)/lib -lHistoxx OBJY_LIB = -L$(OBJY_DIR)/lib -loo.4.02 HEPODBMS_LIB = -L$(HEP_ODBMS_DIR)/lib -lHepODBMS EXTRA_LIBRARIES = $(OTHLIB) $(HISTO_LIB) $(OBJY_LIB) $(HEPODBMS_LIB)This script file is more complex than the previous one because now we need to access the HistOOgram libraries and include files. We will see later in details the HistOOgramRename.cpp file.
The Build options are the same as before.
The Function definition is now:
The definition of the special functions is also the same.
The Input Ports should be defined as follow:

The Output Ports should be defined as follow:

The ouput port HistoOuput should be connected to a Text widget. To do that follow the procedure previously described.
The last operation is to define the file HistOOgramRename.cpp:
#include "HEAdaptors/HEInputParam.h"
#include "HEAdaptors/HEInputHistOO.h"
#include "HEAdaptors/HEOutputHistOO.h"
#include "HEAdaptors/HE2Objy.h"
#include "histograms.h"
extern "C" {
void HistOOgramRename ( void );
void initHook ( void );
void removeHook ( void );
}
static HESessionHelper *helper;
static HEInHistOO *HistoInput;
static HEInParamStr *NewName;
static HEOutHistOO *HistoOutput;
//-----------------------------------------------------------------------------
//
// This function is the kernel of the module.
//
void HistOOgramRename (void) {
helper->startUpdate();
NewName->lookUp();
if (NewName->notEmpty()) {
HepRef(BaseHisto1D) histo_in;
HistoInput->lookUp();
histo_in = (HepRef(BaseHisto1D)&) HistoInput->getValue();
histo_in->set_name(NewName->getValue());
HistoOutput->sendOID(histo_in);
}
helper->commit();
}
//-----------------------------------------------------------------------------
//
// Hook function for Explorer module actions.
// This function is executed once when the module start.
//
void initHook(void)
{
HistoInput = new HEInHistOO("HistoInput");
HistoOutput = new HEOutHistOO("HistoOutput");
NewName = new HEInParamStr("New Name");
// Open FDDB
helper = new HESessionHelper();
if (helper != 0) {
if (helper->fDbCheck () == 0) { // Check if OO_FD_BOOT is defined
removeHook();
exit (1);
}
} else {
cerr << "Can't create session helper" << endl;
exit(1);
}
}
//-----------------------------------------------------------------------------
//
// Hook function for Explorer module actions.
// This funtion is executed when the module stop.
//
void removeHook(void)
{
delete HistoInput;
delete HistoOutput;
delete NewName;
delete helper;
}
The structure of the function is very similar to
the modulename.cpp
one:
The module can then be included in a explorer map:
