Defining a static module
Topics covered in this chapter:
- Example
- Structures for passing information
- Complete module example
- Turning a static module into a DSO
- Static modules versus I/O drivers
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.