Initializing help system before first use

The initialization function

Once a module is loaded in core memory, the Module Manager calls a special function: the initialization function. Through this function, the constant symbols (Section Table of constants), subroutines (Section Table of functions), types (Section Table of types), and services (Section Table of services) that are provided by the module are passed on to Mosel. The control parameters of the module are not communicated in this way, they require the definition of a dedicated service function (Section Service ``Find Parameter'') and the implementation of two specific library functions (Section Table of functions).

In order for Mosel to find this initialization function, it must be named modulename_init (where modulename is the name given to the module) and have the following signature:

DSO_INIT modulename_init(XPRMnifct nifct, int *interver, int *libver,
                         XPRMdsointer **interf)

The parameters are used to exchange information about version numbers and the functionality provided by the module.

  • nifct is a table of functions provided by Mosel that can be called from the module during its processing. They are used to access the data of the running model (see Section Functions of the Native Interface) and is usually saved in a global variable for later use
  • interver is used to tell Mosel which version of the Native Interface is employed for the implementation of this module. This parameter must always be assigned the value XPRM_NIVERS. By default, the interface version is the one of the current Mosel version but it is possible to select an older release (such that the generated module can be used with this release) by defining the macro XPRM_NICOMPAT before including the "xprm_ni.h" header file. This macro must refer to the Mosel target version. For instance:
    #define XPRM_NICOMPAT 3000000
    #include "xprm_ni.h"
    will use the API version of Mosel 3.0.0 (functions introduced after this release are disabled)
  • libver is the version number of the module: it is generated using the macro XPRM_MKVER(M,n,r) where (M,n,r) stands for (major version number, minor version number, release number). Each number must be an integer between 0 and 999.
  • interf is a structure composed of 4 tables (and their respective sizes) describing the constants, the functions, the types and the services implemented by the module

The format of the main interface structure XPRMdsointer is the following:

{
 int sizec; XPRMdsoconst *tabconst;
 int sizef; XPRMdsofct *tabfct;
 int sizet; XPRMdsotyp *tabtyp;
 int sizes; XPRMdsoserv *tabserv;
}

Every table in this structure (constants, subroutines, types, and services) is preceded by its size. The four tables are described in detail in the following sections.

Example:

static XPRMnifct mm;

DSO_INIT mymodule_init(XPRMnifct nifct, int *interver, int *libver,
                       XPRMdsointer **interf)
{
 mm=nifct;                  /* Save the table of NI functions */
 *interver=XPRM_NIVERS;     /* Mosel NI version */
 *libver=XPRM_MKVER(0,0,1); /* Module version */
 *interf=&dsointer;         /* Pass info about module contents to Mosel */
 return 0;
}

Table of constants

Each entry of the table of constants is a pair ( constant name, constant value ). If a constant is to be declared as part of a namespace its name must be fully qualified (e.g. "mynamspc∼mycst"). A module can define integer, real, Boolean and string constants. The initialization of the table can be done using the following macros:

XPRM_CST_INT(char *name, int value)
XPRM_CST_BOOL(char *name, int value)
XPRM_CST_STRING(char *name, char *value)
XPRM_CST_REAL(char *name, static const double value)

Note that for real constants, a static variable has to be provided instead of a constant number.

static const double myreal=12.456;

static XPRMdsoconst tabconst[]=
    {
     XPRM_CST_INT("MYINT", 10),
     XPRM_CST_BOOL("MYBOOL", XPRM_TRUE),
     XPRM_CST_STRING("MYSTR", "text"),
     XPRM_CST_REAL("MYREAL", myreal)
    };

The information provided by the table of constants is used only during the compilation phase of the model: constants are immediatly replaced by their values. As a consequence, a module that only defines constants is only required for the compilation of a model using it; at execution time it is not loaded again.

Table of functions

The table of functions describes the functions, procedures, and operators that will be available in the Mosel language. Each entry of the function table is of the following structure:

{
 char *name;
 int code;
 int type;
 int nbpar;
 char *parstr;
 int (*fct)(XPRMcontext ctx, void *libctx);
}
name:
The name that will be used in the Mosel language. If the subroutine is to be declared as part of a namespace its name must be fully qualified ( e.g. "mynamspc∼myfct").
Note that different subroutines (or operators) may have the same name as long as they are not expecting the same parameters ( overloading). It is also possible to overload a predefined function or procedure with the same restriction as for user defined symbols. Overloading cannot apply between function and procedure ( i.e. a procedure cannot overload a function and vice versa).
code:
An internal code for the subroutine or operator.
This code must be either an integer value ≥1000 or a predefined code. Note that the entries in the table of functions must be sorted in ascending order of their internal code.
type:
The type returned by the routine.
For a function, the possible values are: XPRM_TYP_INT, XPRM_TYP_REAL,
XPRM_TYP_STRING, XPRM_TYP_BOOL to indicate an integer, real, string or Boolean return value respectively. The type must be XPRM_TYP_EXTN if the function returns an entity of a type managed by the module ( i.e. the function is a constructor) — in this case, the first word of the parameter string is the name of this type followed by a colon. If the function returns a set or a list the type must also be XPRM_TYP_EXTN and the first word of the parameter string must start with "&{" for a set or "&[" for a list followed by the element type and a colon. The element type is specified by a letter for basic types (same convention as for the parst) or the letter n and the type name for a native type. If the subroutine is a procedure the type must be XPRM_TYP_NOT.
By default a function returning a non-basic type is considered to be a constructor ( i.e. the returned value is a newly created entity). If such a function returns a reference to an existing entity it must increase the reference count of this object (see Section Reference counting) and have the flag XPRM_FTYP_PTR as part of its type.
Functions the name of which starts with the string "get", returning a basic type ( i.e. integer, real, string or Boolean) and taking as their only argument a native type, linctr or mpvar are identified as attribute accessors (see findattrdesc). For instance the function "getsol(mpvar):real" returns the sol attribute of a decision variable. Adding XPRM_FTYP_NOATTR to the type of a function of this kind prevents Mosel from recording it as an attribute accessor.
nbpar:
The number of parameters required by the routine
parstr:
The parameter string is used to describe the type of each parameter.
This string is composed with the following characters:

i an integer
r a real
s a text string
b a Boolean
v a decision variable (type mpvar)
c a linear constraint (type linctr)
I a range set
a an array (of any kind)
e a set (of any type)
l a list (of any type)
|xxx| external type named `xxx'
!xxx! the set named `xxx'
Andx.t an array indexed by `ndx' of the type `t'. `ndx' is a string describing the type of each indexing set. `ndx' may be omitted in which case any array of type `t' is a valid parameter.
Et a set of type `t'
Lt a list of type `t'
? any type, the routine will receive actually 2 parameters for this marker: the first one, an integer, is the type of the following one (the effective value of the argument)
* must be the last character: the function has a variable number of arguments

If the last character of the parameter string is *, the function accepts a variable number of arguments: the corresponding parameter is a list (possibly empty) containing the supplementary parameters.
Moreover, if the function is of type XPRM_TYP_EXTN, the string starts with the name of the type followed by a colon.
Example: "mytype:ir|mytype|s*" is the signature of a function of type `mytype' expecting at least 4 parameters (integer, real, mytype and string).
The signature for a function that returns a list of text and take a real as only argument will be: "&[ntext:r".
fct:
The function Mosel has to call to perform the operation.
The prototype of all functions must be (see Section Defining subroutines):
int functionname(XPRMcontext ctx, void *libctx);

Example:

static int my_getsol(XPRMcontext ctx, void *libctx);
static int my_getname(XPRMcontext ctx, void *libctx);
static int my_eql(XPRMcontext ctx, void *libctx);
static int my_new(XPRMcontext ctx, void *libctx);

static XPRMdsofct tabfct[]=
    {
     {"getsolarray", 1000, XPRM_TYP_NOT, 2, "aa", my_getsol},
     {"getname", 1005, XPRM_TYP_STRING, 1, "|mytype|", my_getname},
     {"@=", 1011, XPRM_TYP_BOOL, 2, "|mytype||mytype|", my_eql},
     {"@&", 1015, XPRM_TYP_EXTN, 3, "mytype:sri", my_new}
    } 

For details on the definition of operators (such as the third and fourth entries in this example) the reader is referred to Section Special functions/operators.

Table of types

Types introduced by modules are handled by Mosel just like any other standard type (integer, real...). To define a type, some specific functions have to be provided by the module. Each entry of the table of types contains the following items:

name (char *):
The name of the type that will be used in the Mosel language. If the type corresponds to a problem extension, the name must have the form mainpbtyp.extn (see Section Problem types). If the type is to be declared as part of a namespace its name must be fully qualified ( e.g. "mynamspc∼mytype").
code (int):
An internal code for the given type. This code is an integer value not larger than 65535. Note that types must be sorted in ascending order of their internal code.
props (int):
A bit coded set of properties. The supported properties are:
  • XPRM_DTYP_PNCTX: If this flag is set, the function tostring (see below) can be called with a NULL context.
  • XPRM_DTYP_RFCNT: If this flag is set, the module handles reference count for this type. As a consequence Mosel may call the function create (see below) with a reference to a previously created object for increasing its reference count. The function delete (which is mandatory in this case) is then called as many times as the create function has been used for a given object before this object is effectively released. When this property is not available for a type, Mosel handles itself the reference counting: this is in general less efficient except if the type is a problem extension (reference counting is not used in this case).
  • XPRM_DTYP_APPND: If this flag is set, the function copy supports appending.
  • XPRM_DTYP_ORSET: If this flag is set, the function copy can be called only for resetting an object.
  • XPRM_DTYP_PROB: This flag must be set if the type corresponds to a problem.
create function (void *):
The function Mosel has to call for creating an object of this type. The function must return a pointer to this new object or NULL in case of failure. The prototype of create is:
void *(*create)(XPRMcontext ctx, void *libctx, void *ref,int typnum)
This function is mandatory. If the module does not support reference count for this type, the parameter ref is always NULL and can be ignored. Otherwise, the flag XPRM_DTYP_RFCNT has to be set (see above) and whenever this function is called with a valid pointer as the third parameter, the reference count for the corresponding object must be incremented (no new object has to be created). The value returned should be the provided reference. The last parameter is the order number associated to this type for the running model.
delete function (void *):
The function Mosel has to call for deleting an object previously allocated using the create function.
void (*fdelete)(XPRMcontext ctx, void *libctx, void *todel,int typnum)
This function is optional (the entry may be NULL) when reference count is not handled by the module, if defined, it is used to delete local and temporary objects. Note that if reference count is implemented, this function will be called as many times as the create function has been called for a given reference, the object must be deleted only the last time the function is used. The last parameter is the order number associated to this type for the running model.
tostring function (void *):
This function has to be called by Mosel for getting a textual representation of an object.
int (*tostring)(XPRMcontext ctx, void *libctx, void *obj, char *dest,
                int maxsize,int typnum)
The textual representation of obj has to be copied into dest the maximum length of which is maxsize. The reference obj might be NULL: in this case the function is expected to return the textual representation of an entity in its initial state ( i.e. just after having been created). The function must return the length of the generated string or a negative value in case of error. If the string that is to be returned in dest exceeds the given maximum length, function tostring returns the required length but not the string itself : it is then called a second time with a sufficiently large maximum size.
This function is optional (the entry may be NULL), if defined, it is used for displaying values (procedures write/ writeln) and by the initializations to procedure.
fromstring function (void *):
This function has to be called by Mosel for initializing an object from a textual representation.
int (*fromstring)(XPRMcontext ctx, void *libctx, void *obj,
                  const char *src,int typnum, const char **end)
The object obj is initialized with the content of the string src. When the end parameter is not NULL, the pointer to the first character not used by the conversion has to be returned via this parameter. It must receive a copy of src in case of failure. If successful, the function must return 0; any other value is interpreted as a failure.
This function is optional (the entry may be NULL), if defined, it is used by the initializations from procedure.
copy function (void *):
This function is required for assignments not explicitly stated ( e.g. in array initialization or when assigning records) and may be used to generate some assignments (as a replacement for the "@:" and "@P" operators, see section Special functions/operators).
int (*copy)(XPRMcontext ctx, void *libctx, void *dest,void *src,int tnop)
The parameter tnop is bit encoded: it stores both the type order number (which can be extracted using the macro XPRM_TYP(tnop)) and a code indicating what operation to perform. The macro XPRM_CPY(tnop) returns the following operation codes:
  • XPRM_CPY_COPY: The object dest receives the content (or becomes a copy) of src (which may be NULL). This operation is not used if the type has property XPRM_DTYP_ORSET.
  • XPRM_CPY_RESET: The object dest is reset (i.e. it returns to its initial state). This operation is essentially used to implement the reset function of the Mosel language.
  • XPRM_CPY_APPEND: The object dest is extended with a copy of src (which may be NULL). This operation is used if the type property XPRM_DTYP_APPND is set and property XPRM_DTYP_ORSET is not set.
If successful, the function must return 0; any other value is interpreted as a failure.
This function is optional (the entry may be NULL) but if it is missing, the operations where it is necessary are disabled by the compiler for the corresponding type.
compare function (void *):
This function is required for comparison of aggregated objects ( e.g. when testing equality of records including fields of this type).
int (*compare)(XPRMcontext ctx, void *libctx, void *obj1,void *obj2,int tnop)
The parameter tnop is bit encoded: it stores both the type order number (which can be extracted using the macro XPRM_TYP(tnop)) and a code indicating what operation to perform. The macro XPRM_COMPARE(tnop) returns the following operation codes:
  • XPRM_COMPARE_EQ: Test whether obj1 and obj2 are equal.
  • XPRM_COMPARE_NEQ: Test whether obj1 and obj2 are different.
If successful, the function must return a positive value if the comparison is true and 0 otherwise. Error conditions are reported using the special return value XPRM_COMPARE_ERROR.
This function is optional (the entry may be NULL) but if it is missing, the operations where it is necessary are disabled by the compiler for the corresponding type.

Example:

static XPRMdsotyp tabtyp[]=
{
 {"firsttype", 1, 0, createfirst, del1, tostr1, fromstr1,copy1,cmp},
 {"secondtype", 2, XPRM_DTYP_RFCNT, create2, delete2, NULL, NULL, NULL,NULL},
 {"mpproblem.mypb", 3, XPRM_DTYP_PROB, newpb, delpb, NULL, NULL, cppb,NULL}
};

Table of services

Services are special tasks that are not directly linked to the Mosel language itself (that is, they are not visible to the user of a module). Under some particular circumstances, Mosel looks for a service. If this service is implemented by the module, the corresponding function is called. Each entry of the table of services is the pair ( service code, function to call ).

Example:

static XPRMdsoserv tabserv[]=
{
 {XPRM_SRV_RESET,(void *)my_reset},
 {XPRM_SRV_PRIORITY,XPRM_MKPRIORITY(-1)},
 {XPRM_SRV_UNLOAD,(void *)my_unload}
};

Note that all services are optional. See section Defining services for a comprehensive list of services.

© 2001-2019 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.