For general information about toolboxes and gateways, see the Create a toolbox page, and linked pages

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:

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)

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)

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);

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

public: GatewaysFromScilab5ToScilab6 (last edited 2019-01-31 21:53:50 by 91-160-23-12)