How to create and access a list — How to create and access a list 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 [mt]list, to get some elements stored in that this and to send a new [mt]list using a function written in C.
For this, we will wrote two C gateway function in which we will retrieve the [mt]list, and we will create a new [mt]list.
This example is available in SCI/modules/core/example/print_list.
Let's initialize a mlist in Scilab.
A = mlist(['mytype','var1','var2'],'a string',[1 2; 3 4]);
This mlist is of type 'mytype' (typeof(A)=='mytype') and it has 2 elements:
A('var1') which is equal to 'a string'
A('var2') which is equal to [1 2; 3 4]
We now create a C function called sci_print_list which will print the elements stored in the list.
#include <stack-c.h> #include <sciprint.h> int sci_print_list(char * fname) { int m_list_in, n_list_in, l_list_in; int m_type, n_type; int m_var1, n_var1, l_var1; int m_var2, n_var2, l_var2; char ** LabelList = NULL; CheckRhs(1,1); // We accept only 1 parameter GetRhsVar(1,"m",&m_list_in,&n_list_in,&l_list_in); // Get a mlist // Get the type and the name of the variables (the first element of the mlist) GetListRhsVar(1,1,"S",&m_type,&n_type,&LabelList); if (strcmp(LabelList[0],"mytype")!=0) { sciprint("error, you must ship a mlist or type mytype\n"); return 0; } // Get the first variable (a string) GetListRhsVar(1,2,"c",&m_var1,&n_var1,&l_var1); sciprint("var1 = %s\n",cstk(l_var1)); // Get the second variable (a double matrix) GetListRhsVar(1,3,"d",&m_var2,&n_var2,&l_var2); sciprint("var2 = [%f %f %f %f]\n",*stk(l_var2+0), *stk(l_var2+1), *stk(l_var2+2), *stk(l_var2+3)); return 0; }
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 C file is available in the example directory. It is named print_list.c.
// This is the builder.sce // must be run from this directory lines(0); ilib_name = 'lib_print_list'; files = ['print_list.c']; libs = []; table =['print_list', 'sci_print_list']; ldflags = ""; cflags = ""; fflags = ""; ilib_build(ilib_name,table,files,libs,'Makelib',ldflags,cflags,fflags); </programlisting> <para>This file must be saved as "builder.sce".</para> <para>This script will tell Scilab which files must be compiled (here, it's print_list.c), what will be the name of the shared library (here, it's lib_print_list) and which C symbol will be linked to a Scilab function (here, we will link the sci_print_list C symbol to the Scilab function "print_list").</para> <para>To build this function, we just need to to:</para> <programlisting role = ""><![CDATA[ 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. Let's test our new function:
exec builder.sce; exec loader.sce; A = mlist(['mytype','var1','var2'],'a string',[1 2; 3 4]); print_list(A);
This example is available in SCI/modules/core/example/create_list.
We now write a simple example to test our new function to create a [mt]list.
A = create_list(); disp(A);
First, let's write the C function:
#include <stack-c.h> #include <string.h> int sci_create_list(char * fname) { int m_list_out, n_list_out; int m_var1, n_var1, l_var1, l_list_var1; int m_var2, n_var2, l_var2, l_list_var2; int m_mlist, n_mlist, l_mlist; // The labels of our mlist static const char * ListLabels [] = {"mylist","var1","var2"}; // First, we create the variables using a classical way // The size of the Scilab variables m_var1 = 1; n_var1 = strlen("a string")+1; // a null terminated string m_var2 = 2; n_var2 = 2; // A 2x2 double matrix m_mlist = 3; n_mlist = 1; // A mlist with 3 elements // Creation of the Scilab variables // A('var1') CreateVar(1, "c", &m_var1, &n_var1, &l_var1); // A('var2') CreateVar(2, "d", &m_var2, &n_var2, &l_var2); // A CreateVar(3, "m", &m_mlist, &n_mlist, &l_mlist); // We store values in the create variables // The matrix will be stored in A('var2') *stk(l_var2+0) = 1; *stk(l_var2+1) = 2; *stk(l_var2+2) = 3; *stk(l_var2+3) = 4; // The string will be stored in A('var1') strncpy(cstk(l_var1),"a string\0",n_var1); m_list_out = 3; n_list_out = 1; // now, affect the variable to the mlist // The labels (it corresponds to A = mlist(['mylist','var1','var2'], ... CreateListVarFromPtr(3, 1, "S", &m_list_out, &n_list_out, ListLabels); // The value stored in A('var1') (it corresponds to A = ...,'a string', ... CreateListVarFrom(3, 2, "c", &m_var1, &n_var1, &l_list_var1, &l_var1); // The value stored in A('var2') (it corresponds to A = ...,[1 2,3 4]); CreateListVarFrom(3, 3, "d", &m_var2, &n_var2, &l_list_var2, &l_var2); // We return only the mlist which has been created at position 3 LhsVar(1) = 3; return 0; }
Some important comments related to the CreateVar(Pos,"m",&m, &n, &l) function. When called on a mlist, only the m parameter is taken in account, the n parameter is not used. So, be careful:
m_list = 3; n_list = 1; CreateVar(1, "m", &m_list, &n_list, &l_list);
creates a mlist with 3 elements but:
m_list = 1; n_list = 3; CreateVar(1, "m", &m_list, &n_list, &l_list);
creates a mlist with only 1 element !
Another important thing: when we create a list element using CreateListVarFrom, it is not recommended to access the created variable using, for example, stk(l_list_var2) because CreateListVarFrom performs type transformation on the list variables.
// This is the builder.sce // must be run from this directory lines(0); ilib_name = 'lib_create_list'; files = ['create_list.c']; libs = []; table =['create_list', 'sci_create_list']; 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 create_list.c), what will be the name of the shared library (here, it's lib_create_list) and which C symbol will be linked to a Scilab function (here, we will link the sci_create_list C symbol to the Scilab function "create_list").
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. Let's test our new function:
exec builder.sce; exec loader.sce; A = create_list(); disp(typeof(A)) disp(getfield(1,A)) disp(A('var1')) disp(A('var2'))