How to check parameters — how to check parameter send to an interface using the C gateway functions
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.
#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", &m2, &n2, &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.
// 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.
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.