Nom

How to check parameters — how to check parameter send to an interface using the C gateway functions

Description

WARNING: This API is deprecated from Scilab 5.2.0 and is going to be removed with Scilab 6.0. Please use API Scilab (the new Scilab API).

The goal is to get a set of parameters via a set of C gateway functions and then to perform some checks in the C function.

This example is available in the directory core/examples/check_properties.

The C function

 
#include <stack-c.h>
#include <sciprint.h>

int sci_check_properties_1(char * fname)
{
  int m1, n1, l1;
  int m2, n2, l2;
  int m3, n3, l3;
  int m4, n4, l4;
  int m5, n5, l5;

  CheckRhs(5,5);
  CheckLhs(0,1) ;

  ////////////////////////////
  // Getting first argument //
  ////////////////////////////

  GetRhsVar(1, "d", &m1, &n1, &l1);

  CheckVector(1,m1,n1);   // Check that first argument is a vector
  CheckLength(1,m1*n1,4); // Check vector length
  
  /////////////////////////////
  // Getting second argument //
  /////////////////////////////

  GetRhsVar(2, "d", &amp;m2, &amp;n2, &amp;l2);

  CheckRow(2,m2,n2); // Checks that second argument is a row vector
                     // CheckColumn can also be used

  CheckDimProp(1,2, m1 * n1 != n2); // Check compatibility beetween arg 1 and arg 2. We want m1*n1 == n2 

  ////////////////////////////
  // Getting third argument //
  ////////////////////////////

  GetRhsVar(3, "d", &m3, &n3, &l3);

  CheckSameDims(1,3,m1,n1,m3,n3); // Checks that arg 1 and arg3 have same dimensions

  /////////////////////////////
  // Getting fourth argument //
  /////////////////////////////

  GetRhsVar(4,"d",&m4,&n4,&l4);
  
  CheckScalar(4,m4,n4); // arg 4 must be scalar

  /////////////////////////////
  // Getting fourth argument //
  /////////////////////////////

  GetRhsVar(5,"d",&m5,&n5,&l5);
  
  CheckSquare(5,m5,n5);   // square matrix
  CheckDims(5,m5,m5,5,5); // check dimensions

  LhsVar(1)=0;

  return 0;
}

// We must be careful on the scilab name function (8 chars max).

int sci_check_properties_2(char * fname)
{
  int m1,n1,l1;

  CheckRhs(1,1);
  CheckLhs(0,1) ;

  switch(VarType(1)) 
    {
    case 1: 
      GetRhsVar(1, "d", &m1, &n1, &l1);
      sciprint("1 is a scalar matrix\n");
      break;
    case 10:
      GetRhsVar(1, "c", &m1, &n1, &l1);
      sciprint("1 is a string\n");
      break;
    case 5:
      sciprint("1 is a sparse trying to overload\n");
      OverLoad(1);
    }

  LhsVar(1) = 0;

  return 0;
}
 

This file must be saved as "check_properties.c".

The main thing to highlight is that, to build a C gateway function, we need to include the header stack-c.h. In this header, we find the prototypes and macros of the main C gateway functions. We also need to include sciprint.h because we use the sciprint function.

To be able to build and link such a C function to Scilab, we need to write a Scilab script which will compile this C function and then create a loader script which will link the C function to a Scilab function.

The builder script

 
// This is the builder.sce 
// must be run from this directory 

lines(0);

ilib_name  = 'lib_check_properties';

files = ['check_properties.c'];

libs  = [];

table =['check_properties_1', 'sci_check_properties_1'; ...
        'chprop2',            'sci_check_properties_2'];

// We must be careful when we choose a scilab function name in case of overloading.
// We Scilab name function must be 8 char max.

ldflags = "";
cflags  = "";
fflags  = "";

ilib_build(ilib_name,table,files,libs,'Makelib',ldflags,cflags,fflags);
 

This file must be saved as "builder.sce".

This script will tell Scilab which files must be compiled (here, it's check_properties.c), what will be the name of the shared library (here, it's lib_check_properties) and which C symbol will be linked to a Scilab function (here, we will link the sci_check_properties_1 C symbol to the Scilab function "check_properties_1").

For the other C function, we must be careful on the name of the Scilab function we will choose. Because this function will be overloading, the current overloading process of Scilab works only on Scilab primitives (Scilab function wrote in C) which have a name which is maximum 8 char wide.

For this function, we will link the sci_check_properties_2 C symbol to the Scilab function "chprop2").

To build this function, we just need to to:

  
exec builder.sce;
 

Now we are able to test our new C function. First, let's load this new function in scilab:

 
exec loader.sce; 
 

The script loader.sce is normally automatically built by builder.sce.

Testing our new function

We now write a simple example to test our new functions.

 
// checks arguments compatibility 

check_properties_1([1;2;3;4],[3,4,5,6],[6;7;8;9],90,rand(5,5))

// first argument can have different types 

chprop2([1,2,2]);
chprop2('foo');

// overload case 

deff('[]=%sp_chprop2(sp)','disp(''sparse overloaded'')');
chprop2(sparse([1,2,3]));

// tests which give an error message with check_properties_1

try
  check_properties_1([1;2;3;4]',[3,4,5,6],[6;7;8;9],90,rand(5,5))
catch
  disp(lasterror());
end

try
  check_properties_1([1;2;3;4],[3,4,5,6]',[6;7;8;9],90,rand(5,5))
catch
  disp(lasterror());
end

try
  check_properties_1([1;2;3;4],[3,4,5,6],[6;7;8;9]',90,rand(5,5))
catch
  disp(lasterror());
end

try
  check_properties_1([1;2;3;4],[3,4,5,6],[6;7;8;9],[],rand(5,5))
catch
  disp(lasterror());
end

try
  check_properties_1([1;2;3;4],[3,4,5,6],[6;7;8;9],90,rand(4,4))
catch
  disp(lasterror());
end
 

The script must be saved as "check_properties.sce".

Let's run our scripts and see what is the result:

  
-->exec builder.sce;
   Génère un fichier gateway
   Génère un fichier loader
   Génère un Makefile : Makelib
   Exécute le makefile
   Compilation de check_properties.c
   Construction de la bibliothèque partagée (soyez patient)
 
-->;exec loader.sce;
Bibliothèque partagée chargée.
Link done.
 
-->exec check_properties.sce;
1 is a scalar matrix
1 is a string
1 is a sparse trying to overload
 
 sparse overloaded   
 
 check_properties_1 : Les paramètres first et third a des dimensions incompatibles (1x4) # (4x1)   
 
 check_properties_1: second paramètre devrait être un vecteur ligne   
 
 check_properties_1 : Les paramètres first et third a des dimensions incompatibles (4x1) # (1x4)   
 
 check_properties_1: fourth paramètre devrait être un scalaire   
 
 check_properties_1 : Argument numéro 5 n'a pas les bonnes dimensions (4,4),  (5,5) attendues.    
 

See Also

GetRhsVar, CheckColumn, CheckDims, CheckRow, CheckScalar, CheckVector, CheckDimProp, CheckLength, CheckSameDims, CheckSquare, OverLoad, ilib_build