Please note that the recommended version of Scilab is 2025.0.0. This page might be outdated.
However, this page did not exist in the previous stable version.
How to access a matrix
How to access a matrix 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 matrix of doubles send to a function written in C.
For this, we will wrote a C gateway function in which we will retrieve the matrix, we will perform some simple steps in this C function:
First, we will get an access to the matrix in the Scilab memory
We will perform some simple operations on the matrix (in this example, we will multiply by 2 each elements of the matrix)
We will return the result to Scilab
This example is available in the directory SCI/modules/core/examples/ex1.
The C function
#include <stack-c.h> int sci_multiply_by_two(char * fname) { int m_in_var, n_in_var, l_in_var; int m_out_var, n_out_var, l_out_var; int i_row, j_col; double * pMatrix = NULL; // First, access to the input variable (a matrix of doubles) GetRhsVar(1, MATRIX_OF_DOUBLE_DATATYPE, &m_in_var, &n_in_var, &l_in_var); // Create the returned variable (a matrix of doubles) m_out_var = m_in_var; n_out_var = n_in_var; CreateVar(2, MATRIX_OF_DOUBLE_DATATYPE, &m_out_var, &n_out_var, &l_out_var); pMatrix = stk(l_in_var); // Perform some simple operations on the matrix for(i_row=0; i_row<m_in_var; i_row++) { for(j_col=0; j_col<n_in_var; j_col++) { pMatrix[i_row + j_col * m_out_var] = 2 * pMatrix[i_row + j_col * m_in_var]; } } // Return the output variable LhsVar(1) = 2; return 0; }
This file must be saved as "multiply_by_two.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.
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_multiply_by_two'; files = ['multiply_by_two.c']; libs = []; table =['multiply_by_two', 'sci_multiply_by_two']; 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 multiply_by_two.c), what will be the name of the shared library (here, it's lib_multiply_by_two) and which C symbol will be linked to a Scilab function (here, we will link the sci_multiply_by_two C symbol to the Scilab function "multiply_by_two").
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 function.
A = [1 2 3 4 5; 6 7 8 9 10; 11 12 13 14 15]; B = multiply_by_two(A); disp(B);
The script must be saved as "test.sce".
Let's run our scripts and see what is the result:
-->exec builder.sce; Generate a gateway file Generate a loader file Generate a Makefile ilib_gen_Make: Copy compilation files (Makefile*, libtool...) to TMPDIR ilib_gen_Make: Copy multiply_by_two.c to TMPDIR ilib_gen_Make: Copy lib_multiply_by_two.c to TMPDIR ilib_gen_Make: Modification of the Makefile in TMPDIR. Running the makefile -->exec loader.sce; Shared archive loaded. Link done. -->exec test.sce; 2. 4. 6. 8. 10. 12. 14. 16. 18. 20. 22. 24. 26. 28. 30. -->
This simple function has produced a new matrix which corresponds to the matrix transmitted as an input argument and for which each element of the matrix has been multiplied by 2.
Rebuilding a gateway function
Let's imagine that our gateway function has already been build and we would like to make some changes in our function (multiply by 3 instead of 2).
How do we perform such a changes without restarting Scilab ?
First, we need to list all the dynamic libraries which has been loaded into Scilab. The can be done using the link('show') function:
-->link('show') Number of entry points 1. Shared libraries : [ 0 ] : 1 libraries. Entry point lib_multiply_by_two in shared library 0. ans = 0.
Here, in our current Scilab session, only 1 dynamic library has been loaded. This library has a reference number. For our library, it's "0". Now that we know the reference number of our library, we are able to:
unload this library (using the function ulink(0) - 0 is the reference number of our library)
perform some modification in the source code of our C gateway function (replace multiply by 2 by 3)
rebuild the C gateway function (exec builder.sce;)
load the modified C gateway function into scilab (exec loader.sce;)
This is what is done is the following example:
-->ulink(0) -->exec builder.sce; Generate a gateway file Generate a loader file Generate a Makefile ilib_gen_Make: Copy compilation files (Makefile*, libtool...) to TMPDIR ilib_gen_Make: Copy multiply_by_two.c to TMPDIR ilib_gen_Make: Copy lib_multiply_by_two.c to TMPDIR ilib_gen_Make: Modification of the Makefile in TMPDIR. Running the makefile -->exec loader.sce; Shared archive loaded. Link done. -->exec test.sce; 3. 6. 9. 12. 15. 18. 21. 24. 27. 30. 33. 36. 39. 42. 45.
See Also
<< Calling a scilab function (macros) from a C gateway | How to | How to check parameters >> |