For general information about toolboxes and gateways, see the Create a toolbox page, and linked pages
Contents
Gateways: from Scilab 5 to Scilab 6
This page describes how to port a gateway from Scilab 5 to Scilab 6.
First are described some changes in Scilab 6 that concern the development of gateways. The next sections cover the different possibilities on the porting of gateways.
Changes in Scilab 6
Scilab 6 has brought major changes, following is a brief description.
Memory management
The way Scilab manages memory has totally changed between Scilab 5 and 6. This change has no direct impact on the development of the gateways, however.
Scilab 5
Scilab 5 (and previous versions) have its own memory management system. In this system, Scilab manages a memory space called the stack, which has a maximum size. All the data are stored in the stack, and Scilab cannot access data outside it.
Scilab 6
Scilab 6 does not use the stack system any more and uses the Operating System memory manager instead. Which means that Scilab is not limited any more, and can use all the available memory to store its data.
APIs
Scilab 5
The core module provides several APIs (stack1.h, ..., stack3.h) dedicated to data access and management in the stack.
Scilab 5.3 has introduced the Scilab API, a C API which offers a more abstract way to access Scilab data. This API is nearly fully compatible with the old stack API.
Scilab 6
Scilab 6 API is a new C++ API which simplifies much the data access and management and brings new features like access to user type data, and so on.
The Scilab C API can still be used in Scilab 6 with little modifications. For example, gateway prototypes changes.
Porting gateways
Two possible strategies
As described in the previous section, Scilab 6 introduces a new C++ API.
Therefore there are two ways of porting the gateway code:
- Port it to the new Scilab 6 C++ API.
- The advantages is that the code is simpler, and can benefit of new features of the C++ API. The drawback is the code is only compatible with Scilab 6 (compiles in Scilab 6).
- Keep the C API and port the code to the Scilab 6 C API.
- The advantage is that it requires little modifications. And you can have a gateway compatible Scilab 5 and 6 (i.e. compiles with no modification in Scilab 5 and Scilab 6). The drawback is that the code does not benefit from the simplicity of the C++ API.
What about Fortran ?
Fortran is not supported any more for gateways implementations (but still supported for sources used by gateways).
The Fortran gateway code must be rewritten using one of the strategies above.
Port to the Scilab 6 C++ API
Prototype
Scilab 5
In Scilab 5, gateway functions are:
int sci_foo(char *fname, unsigned long fname_len)
int (return)
- Return code to the Scilab engine but is not used.
fname
- The function name declared in Scilab, and is used for error messages.
fname_len
Used in Fortran gateways (it gives the length of fname), not used in C gateways.
- Input and output arguments are accessed through API functions.
Scilab 6
In Scilab 6, gateway functions have the following prototype:
types::Function::ReturnValue sci_foo(types::typed_list &in, int iRetCount, types::typed_list &out)
types::Function::ReturnValue (return)
- An enum containing the return code of the gateway.
- Possible values:
return types::Function::OK;
return types::Function::OK_NoResult;
return types::Function::Error;
Please see modules/types/includes/function.hxx for more details.
in
- A list containing the datas corresponding to each argument given in Scilab.
Example: foo(arg1, arg2.field, 42, "bar", [0 0 0])
In sci_foo, in will have 5 elements (in.size == 5).
- Each element contains all the informations (type, dims, raw data, ...) corresponding to the "variable" given from Scilab.
Please see modules/types/includes/types.hxx for more details.
- A list containing the datas corresponding to each argument given in Scilab.
iRetCount
- The number of output argument requested.
Example: [out1, out2] = foo()
in this case iRetCount is set to 2.
- It is up to the gateway to return two arguments, knowing two are requested.
Example: foo()
in this case iRetCount is set to 1 (out[0] will be available in Scilab as ans).
- One can try to optimize inner workings according to what results are expected.
- The number of output argument requested.
out
- A list that has to be populated with results that must be returned to Scilab.
Input arguments
Check the number of input arguments
The following example checks there is only one input argument.
Scilab 5
With the Stack API:
CheckRhs(1, 1);
Or:
if (Rhs != 1)
...
With the Scilab API:
CheckInputArgument(pvApiCtx, 1, 1);
Or:
if (nbInputArgument(pvApiCtx) != 1)
...
Scilab 6
The number of arguments is stored in the input argument list property:
if (in.size() != 1)
...
Check the input argument type
In the following example we check the first input argument is a complex matrix.
Scilab 5
With the Stack API:
int iType = GetType(1);if (iType != 1) // 1 is the ID of the type for real or complex
...
if (iIsComplex(1))
...
Types are defined in modules/core/includes/stack-c.h.
With the Scilab API:
int *addr = NULL;
getVarAddressFromPosition(pvApiCtx, 1, &addr);
if (isDoubleType(pvApiCtx, addr) == FALSE)
...
if (isVarComplex(pvApiCtx, addr))
...
Types defined by Scilab API are in modules/api_scilab/includes/api_scilab.h.
Scilab 6
if (in[0]->isDouble() == FALSE)
...
types::Double *pIn = in[0]->getAs<types::Double>();
if (pIn->isComplex())
...
The types in Scilab 6 are defined in modules/ast/includes/types/internal.hxx
Get the input argument data
In this example we get data of a the (first input argument) complex matrix.
iRows will contain the number of rows and iCols the number of columns of the matrix.
pdblRealData will be the array of all real parts.
pdblImgData will be the array of all imaginary parts.
Scilab 5
In Scilab 5, data dimensions and data values are get at same time.
int *addr = NULL;
int iRows = 0;
int iCols = 0;
double *pdblRealData = NULL;
double *pdblImgData = NULL;
getVarAddressFromPosition(pvApiCtx, 1, &addr);
getComplexMatrixOfDouble(pvApiCtx, addr, &iRows, &iCols, &pdblRealData, &pdblImgData);
Scilab 6
types::Double *pIn = in[0]->getAs<types::Double>();
int iRows = pIn->getRows();
int iCols = pIn->getCols();
types::Double *pIn = in[0]->getAs<types::Double>();
double *pdblRealData = pIn->getReal();
double *pdblImgData = pIn->getImg();
Output arguments
Check the number of output arguments
In this example we check the number of input arguments is between 2 and 5.
Scilab 5
With the Stack API:
CheckLhs(2, 5);
Or
if (Lhs < 2 || Lhs > 5)
...
With the Scilab API:
CheckOutputArgument(2, 5);
Or:
if (nbOutputArgument(pvApiCtx) < 2 || nbOutputArgument(pvApiCtx) > 5)
...
Scilab 6
if (iRetCount < 2 || iRetCount > 5)
...
Create the output argument data
Here we create an output complex matrix with 4 rows and 4 columns.
Scilab 5
With the Stack API:
This variable is allocated in the Scilab stack at position Rhs + 1.
int iRows = 4;
int iCols = 4;
double *pdblRealData = NULL;
double *pdblImgData = NULL;
allocComplexMatrixOfDouble(Rhs + 1, iRows, iCols, &pdblRealData, &pdblImgData);
With the Scilab API:
int iRows = 4;
int iCols = 4;
double *pdblRealData = NULL;double *pdblImgData = NULL;
createComplexMatrixOfDouble(pvApiCtx, NbInputArgument(pvApiCtx) + 1, iRows, iCols, &pdblRealData, &pdblImgData);
Scilab 6
types::Double *pRetVal = new types::Double(iRows, iCols, &pdblRealData, &pdblImgData);
Return the output argument
Following shows how to set the output data at the first output argument position (so the number of input arguments + 1).
Scilab 5
With the Stack API:
LhsVar(1) = Rhs + 1;
PutLhsVar();
With the Scilab API:
AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1;
Scilab 6
Append pRetVal (pointing to the result object) in the output list.
out.push_back(pRetVal);
Port to the Scilab 6 C API
Prototype
The gateway prototype in the Scilab 6 C API is:
int sci_foo(char *fname, void *pvApiCtx);
fname
- The Scilab function name, used for error messages.
pvApiCtx
fname_len has disappeared, the second input argument is the API context pointer.
- It is used the same way as in Scilab 5, except it must be passed locally.
Any other "sub" function that calls api_scilab functions (explicitely using pvApiCtx or not) must have their prototypes and calls updated throughout .c/.h/.cxx/.hxx files to pass pvApiCtx locally.
We suggest keeping the name "pvApiCtx" for compatibility with Scilab 5 and ease of update (macros such as GetRhs will still work that way).
Using the preprocessor, you can have a gateway compatible with the Scilab 5 and 6 APIs:
#if SCI_VERSION_MAJOR < 6
int sci_foo(char *fname, unsigned long fname_len);
#else
int sci_foo(char *fname, void *pvApiCtx);
#endif
If other sub-functions use pvApiCtx, make sure the API context pointer is always named exactly "pvApiCtx" so that in Scilab 5 the global pointer is passed.
MALLOC.h
Another change is on MALLOC.h which has replaced by sci_malloc.h in Scilab 6. These files define the MALLOC, CALLOC and REALLOC functions.
Using again the preproccessor, the following code is compatible with Scilab 5 and 6:
#if SCI_VERSION_MAJOR < 6
#include "MALLOC.h"
#else
#include "sci_malloc.h"
#endif