Initializing help system before first use

Implementing the new subroutine

We now implement the new subroutine, which has to perform the following steps:

  • Get the variable and solution arrays from the stack.
  • Check whether the arrays are correct: verify the types, compare the array sizes and the indexing sets.
  • Get the solution for all variables and copy it into the solution array.

The prototype of any library function that implements a subroutine or operator (that is, anything that is passed to Mosel via the list of subroutines structure XPRMdsofct) is fixed by Mosel:

int functionname(XPRMcontext ctx, void *libctx);

The first argument is the context of Mosel, the second the context of the module (see Section Mosel and module contexts for further detail). This module does not define its own context, we therefore do not use this parameter. The return value of the function indicates whether it was executed successfully.

The prescribed prototype of the library function does not allow any parameters to be passed directly; instead, these must be obtained from the stack of Mosel (see Section Working with the Mosel stack for details). In the present case, the stack is accessed via the macro XPRM_POP_REF, meaning that a reference (here: array pointer) is taken from the stack. The parameter values always must be taken in the same order as they appear in the subroutine in the Mosel program.
When the library function implements a function, its return value must be put onto the stack. Since in our example we want to implement a procedure, there is no return value.

Here is the code of the module. For clarity's sake we omit the error handling in function ar_getsol. The same example complete with error handling, is provided with the module examples of the Mosel distribution.

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

#define MAXDIM 20

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

/* List of subroutines */
static XPRMdsofct tabfct[]=
    {
     {"solarray", 1000, XPRM_TYP_NOT, 2, "A.vA.r", ar_getsol}
    };
	
/* Interface structure */
static XPRMdsointer dsointer=
    {
     0, NULL,
     sizeof(tabfct)/sizeof(XPRMdsofct), tabfct,
     0, NULL,
     0, NULL
    };

/* Structure for getting function list from Mosel */
static XPRMnifct mm;

/* Module initialization function */
DSO_INIT solarray_init(XPRMnifct nifct, int *interver,int *libver,
                       XPRMdsointer **interf)
{
 mm=nifct;                  /* Get the list of Mosel functions */
 *interver=XPRM_NIVERS;     /* Mosel NI version */
 *libver=XPRM_MKVER(0,0,1); /* Module version: must be <= Mosel NI version */
 *interf=&dsointer;         /* Pass info about module contents to Mosel */

 return 0;
}

static int ar_getsol(XPRMcontext ctx,void *libctx)
{
 XPRMarray varr, solarr;
 XPRMmpvar var;
 int indices[MAXDIM];

/* Get variable and solution arrays from stack in the order that they are
  used as parameters for `getsol' */
 varr=XPRM_POP_REF(ctx);
 solarr=XPRM_POP_REF(ctx);

/* Error handling:
   - compare the number of array dimensions and the index sets
   - make sure the arrays do not exceed the maximum number of dimensions MAXDIM
*/

/* Get the solution values for all variables and copy them into the solution
   array */
 if(!mm->getfirstarrtruentry(varr,indices))
  do
  {
   mm->getarrval(varr,indices,&var);
   mm->setarrvalreal(ctx,solarr,indices,mm->getvsol(ctx,var));
  } while(!mm->getnextarrtruentry(varr,indices));

 return XPRM_RT_OK;
}