Subsections

 
31.2 Configure the OEInterface

Configuring an OEInterface is the process of telling the name, type and other details of all the command line parameters the program is going to use. It does not include the process of parsing the command line to set the parameter values however.

Configuring always includes the following data

  1. The name of each parameter (e.g., -x, -str, -cutoff).
  2. The type of each parameter (e.g., float, int, string)

and optionally includes

  1. A default value for the parameter, which will be used if the parameter is not specified by the user on the command line.
  2. A one line description of the parameter, which will be displayed to users using standardized -help functions.
  3. A multi line description of the parameter, which will be display to users using standardized -help functions.
  4. Restriction on what values of the parameter are legal. For example a float parameter could be configured to only accept positive values from the user and throw an error if a negative value is given.
  5. A flag specifying that the parameter is required. If a parameter is required the program will throw an error if the user does not specify that parameter when he or she runs the program.
  6. A visiblity level, which controls when the parameter appears when the user call the standardized -help functions.
  7. One or more aliases for the parameter name, which are generally used to create shorthand for lengthy parameter names. For example a parameter names -energy_cutoff_window could be given an alias -ecw, which would make typing ``-energy_cutoff_window 10.0'' on the command line equivalent to ``-ecw 10.0.''

Configuration of the OEInterface is normally done by parsing a text configuration file that is compiled into the program. The format of the text configuration file is described in the API documentation of OEConfigure of the OESystem library. Briefly the format is a series of parameter records of the form:

!PARAMETER <name> [order priority]
  !TYPE <type>
  !ALIAS <alias>
  !BRIEF <brief description>
  !DEFAULT <default value>
  !REQUIRED <true or false>
  !VISIBILITY <visibility>
  !KEYLESS <keyless setting>
  !LEGAL_VALUE <value>
  !ILLEGAL_VALUE <value>
  !LEGAL_RANGE <hi value> <low value>
  !ILLEGAL_RANGE <hi_value> <low_value>
  !DETAIL
    <detailed description line 1>
    <detailed description line 2>
    <detailed description line 3>
    .
    .
    .
!END

Note that only numeric parameters can have legal and illegal ranges.

31.2.1 Compiling the text configuration file into a program

To compile a configuration text file into a program we first need to convert the file into C/C++ code that we can embed in the program. The C++ program text2hex.cpp (which is included in your oechem distribution) takes a text file and creates a C/C++ code snippet that declares an unsigned char array initialized to have the contents of the input file. The text2hex.cpp file may be compiled into the text2hex executable that is used in the example below.

The program takes two inputs, the first being the name of the text file to process, and the second being the name of the array variable. The output is sent to standard out. So example usage would be

text2hex text.txt TextArray > text.cpp

We could simply call this script manually every time we make an update to text.txt, but the whole process can become much more automatic if the following rule is embedded in your makefile.

.SUFFIXES:      .txt
.SUFFIXES:      .itf
.txt.itf:
                text2hex $< InterfaceData > $@

This rule tells the Makefile how to take a text file with a txt extension and create a C/C++ code snippet with a character array named InterfaceData in a new file with the same name with a .itf extension (e.g., foo.txt becomes foo.itf). We choose to use .itf instead of .cpp so that the generated file is not confused with a user created cpp file, even though the itf file is just cpp code.

Now we embed the .itf file in a regular user created .cpp file, as we did in the first example above, and make the .cpp file dependend on the .itf file. So for example, if we have a text configuration file foo.txt and foo.cpp is our regular .cpp file that will have #include "foo.itf", the rule we would create in the Makefile is

foo.o: foo.itf

Once this is setup the process is automatic. Any changes to foo.txt are detected durring the normal make process and the foo.itf file included by foo.cpp is automatically updated and a re-compile of foo.o is forced.

We can make now make use of the compiled in text file by using the OEConfigure function call in OESystem library. As in the following foo.cpp file.

#include "oesystem.h"
using namespace OESystem;

//This defines InterfaceData
#include "foo.itf"

bool ConfigureMyInterface(OEInterface& interface)
{
  //This call configures interface with the InterfaceData
  return OEConfigure(interface,InterfaceData);
}

31.2.2 Configuring Examples

When initially constructed the OEInterface object does not know about any command line parameters. This is demonstrated using the following program.

 1 #include "openeye.h"
 2 #include "oeplatform.h"
 3 #include "oesystem.h"
 4
 5 using namespace OEPlatform;
 6 using namespace OESystem;
 7
 8 int main(int, char**)
 9 {
10   OEInterface itf;
11   OEWriteSettings(itf,oeout,true);
12   return 0;
13 }

Listing:31.3 Command Line Parameters 1

The function OEWriteSettings lists the current settings of all the parameters the OEInterface class knows about. Since it was just constructed the OEInterface class doesn't know about any parameters and the output of the program when run looks like this

Command Line Parameters 1: output

> CommandLineParameters1
#Interface settings
>

indicating the OEInterface doesn't know anything about any parameters yet.

The OEInterface class can be configured either by explicitly calling the various member functions of the class (detailed in the API documentation), or by using the OEConfigure free function in the OESystem library. Taking our previous example we can add an OEConfigure call as follows

 1 #include "openeye.h"
 2 #include "oeplatform.h"
 3 #include "oesystem.h"
 4
 5 //Defines static const unsigned char* array InterfaceData
 6 #include "ch32-3.itf"
 7
 8 using namespace OEPlatform;
 9 using namespace OESystem;
10
11 int main(int , char** )
12 {
13   OEInterface itf;
14   OEConfigure(itf,InterfaceData);
15   OEWriteSettings(itf,oeout,true);
16   return 0;
17 }

Listing:31.4 Command Line Parameters 2

The OEConfigure function is passed the itf object, and a pointer, InterfaceData, to a text file compiled into the program at compile time using the method described in the previous section. For this example the text file is

 1 !PARAMETER -x
 2   !TYPE float
 3 !END
 4
 5 !PARAMETER -y
 6   !TYPE float
 7 !END
 8
 9 !PARAMETER -op
10   !TYPE string
11 !END

Listing:31.5 InterfaceData txt file for Command Line Parameters 2

and given the output of the program is

Command Line Parameters 2: output

> CommandLineParameters2
#Interface settings
#-op (Not set, no default)
#-x (Not set, no default)
#-y (Not set, no default)
>

The example program now lists the three parameters that were configured by the OEConfigure function, using the txt file listed above. Rules for the format of this file are listed in the API documentation of OEConfigure.

Note that because all we have done is configure the OEInterface these parameters have no value set, even though the parameter names and types are now known to the OEInterface class.