Initializing help system before first use

Defining a static module

Topics covered in this chapter:

Modules are libraries that provide additional functionality for the Mosel language. They are usually created as dynamic shared objects that can be used independently of the way a Mosel program is executed. If however, a Mosel program is compiled and run from within a C program (using the Mosel libraries), it is possible to include the definition of a module used by the Mosel program into the C program, thus creating a static module. Such a static module is only visible to and usable by Mosel programs that are executed from this C program. (The C file is compiled into a standard object file, no .dso file is created for the module.)

This chapter gives an example of a typical use of such a static module: for a Mosel program that is embedded into some large application it certainly is preferable to load data already held in memory directly into the model structures and not having to pass them via data files.

Example

We would like to initialize an array of integers in a Mosel program with data held in the C program that executes it:

model "Test initialization in memory"
 uses "meminit"

 parameters
  MEMDAT=''              ! Location of data in memory
  MEMSIZ=0               ! Size of the data block (nb of integers)
 end-parameters

 declarations
  a:array(1..20) of integer
 end-declarations

 writeln("Data located at ", MEMDAT, " contains ", MEMSIZ, " integers")
 meminit(a, MEMDAT, MEMSIZ)
 writeln("a=", a)

end-model

A C program to execute the Mosel program meminit_test.mos printed above may look as follows:

int main()
{
 XPRMmodel mod;
 int result;
 char params[80];
 static int tabinit[]= {23,78,45,90,234,111,900,68,110};

 XPRMinit();                                       /* Initialize Mosel */
 XPRMcompmod("", "meminit_test.mos", NULL, NULL);  /* Compile the model */
 mod=XPRMloadmod("meminit_test.bim", NULL);        /* Load the model */

 /* Parameters: the address of the data table and its size */
 sprintf(params, "MEMDAT='%p', MEMSIZ=%d", tabinit, sizeof(tabinit)/sizeof(int));

 XPRMrunmod(mod, &result, params);                 /* Run the model */
 return result;
}

Structures for passing information

A static module differs from dynamic modules only in the way it is initialized. The module initialization function (see below Section Initialization function) has no special return type to make it known to Mosel, instead it is declared to Mosel in the main C program. After the initialization of Mosel, but before any model file that uses the static module meminit is compiled or loaded, we have to add the following line:

 XPRMregstatdso("meminit", meminit_init);

The function XPRMregstatdso registers the module name and its initialization function with Mosel.

List of subroutines

The module meminit only defines a single subroutine, namely the procedure meminit. This procedure takes three arguments (see Appendix List of subroutines for an explanation of the encoding of the parameter format string): AI.i: an array of integers indexed by a range (the data we want to pass to the model), s: a string (the location of the data in memory) and i: an integer (the size of the data array):

static XPRMdsofct tabfct[]=
    {
     {"meminit", 1000, XPRM_TYP_NOT, 3, "AI.isi", mi_meminit}
    };

This table of functions needs to be included into the main interface structure as shown in the previous chapters.

Initialization function

As mentioned earlier, the prototype of the initialization function for static modules is slightly different from what we have seen for DSOs, but the information exchanged between Mosel and the module is the same:

static int meminit_init(XPRMnifct nifct, int *interver, int *libver,
                        XPRMdsointer **interf)
{
 mm=nifct;                      /* Save the table of functions */
 *interver=XPRM_NIVERS;         /* The interface version we are using */
 *libver=XPRM_MKVER(0,0,1);     /* The version of the module: 0.0.1 */
 *interf=&dsointer;             /* Our interface */
 return 0;
}

Complete module example

Below follows the complete code of the static module meminit and the main function that declares this module and executes the Mosel model which requires the module.

#include <stdio.h>
#include <stdlib.h>
#include "xprm_mc.h"
#include "xprm_ni.h"

static int meminit_init(XPRMnifct nifct, int *interver, int *libver,
                        XPRMdsointer **interf);

/* Main function */
int main()
{
 XPRMmodel mod;
 int result;
 char params[80];
 static int tabinit[]= {23,78,45,90,234,111,900,68,110};

 XPRMinit();                                       /* Initialize Mosel */

 /* Register `meminit' as a static module (=stored in the program) */
 XPRMregstatdso("meminit", meminit_init);

 XPRMcompmod("", "meminit_test.mos", NULL, NULL);  /* Compile the model */
 mod=XPRMloadmod("meminit_test.bim", NULL);        /* Load the model */

 /* Parameters: the address of the data table and its size */
 sprintf(params, "MEMDAT='%p', MEMSIZ=%d", tabinit, sizeof(tabinit)/sizeof(int));

 XPRMrunmod(mod, &result, params);                 /* Run the model */
}

/ ******************** **** Body of the module 'meminit'  ******************** ****/

static int mi_meminit(XPRMcontext ctx, void *libctx);

/* List of subroutines */
static XPRMdsofct tabfct[]=
    {
     {"meminit", 1000, XPRM_TYP_NOT, 3, "AI.isi", mi_meminit}
    };

/* Main interface structure */
static XPRMdsointer dsointer=
    {
     0, NULL,
     sizeof(tabfct)/sizeof(XPRMdsofct), tabfct,
     0, NULL,
     0, NULL
    };

static XPRMnifct mm;            /* To store the mosel function table */

/* Initialization function of the module */
static int meminit_init(XPRMnifct nifct, int *interver, int *libver,
                        XPRMdsointer **interf)
{
 mm=nifct;                      /* Save the table of functions */
 *interver=XPRM_NIVERS;         /* The interface version we are using */
 *libver=XPRM_MKVER(0,0,1);     /* The version of the module: 0.0.1 */
 *interf=&dsointer;             /* Our interface */

 return 0;
}

/* Implementation of procedure `meminit' */
static int mi_meminit(XPRMcontext ctx, void *libctx)
{
 XPRMarray arr;
 XPRMstring adr_s;
 XPRMset ndxset;
 int *adr,siz,index[1],last,i;

 arr=XPRM_POP_REF(ctx);             /* The array */
 adr_s=XPRM_POP_STRING(ctx);        /* Data location (as a string) */
 siz=XPRM_POP_INT(ctx);             /* Data size */
 sscanf(adr_s,"%p",&adr);           /* Get the address from the string */

 mm->getarrsets(arr,&ndxset);
 index[0]=mm->getfirstsetndx(ndxset);
 last=mm->getlastsetndx(ndxset);
 for(i=0;(i<siz) && (index[0]<=last);i++,index[0]++)
  mm->setarrvalint(ctx,arr,index,adr[i]);
 return XPRM_RT_OK;
}

Turning a static module into a DSO

It requires only little work to transform a static module into a dynamic one (and vice versa). Assuming we would like to turn our module meminit into a DSO, we simply have to

  • save all the functions of the module and the definition of the structures for passing information into a separate file;
  • replace the prototype of the module initialization function by the following:
     DSO_INIT meminit_init(XPRMnifct nifct, int *interver, int *libver,
                           XPRMdsointer **interf)

Static modules versus I/O drivers

The generalization of the notion `file' and the introduction of I/O drivers in Mosel replace certain uses of static user modules. In particular for transfering data in memory it is often no longer necessary to write a dedicated module. However, other uses of static modules persist, such as the compilation of a standard module as a static module for debugging purposes.

The example from Section Example may be re-written as follows using the raw and mem drivers that are available with the standard distribution of Mosel:

model "Test initialization in memory (I/O)"
 parameters
  MEMDAT=''              ! Data block in memory
 end-parameters

 declarations
  a:array(1..20) of integer
 end-declarations

 initializations from "raw:"
  a as MEMDAT
 end-initializations

 writeln("a=", a)
end-model

The complete C program to execute the Mosel program meminitio.mos printed above may look as follows:

#include <stdio.h>
#include "xprm_mc.h"

int main()
{
 XPRMmodel mod;
 int result;
 char params[80];
 static int tabinit[]= {23,78,45,90,234,111,900,68,110};

 XPRMinit();                                       /* Initialize Mosel */
 XPRMcompmod("", "meminitio.mos", NULL, NULL);     /* Compile the model */
 mod=XPRMloadmod("meminitio.bim", NULL);           /* Load the model */

 /* Parameters: the address of the data table and its size */
 sprintf(params, "MEMDAT='noindex,mem:%p/%u'", tabinit, sizeof(tabinit));

 XPRMrunmod(mod, &result, params);                 /* Run the model */
 return result;
}

© 2001-2025 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.