Scilab Bag Of Tricks: The Scilab-2.5.x IAQ (Infrequently Asked Questions) | ||
---|---|---|
Prev | Chapter 7. Scilab Core | Next |
Analogously to the Fortran-77 section, Section 7.5, following provides a reference for the C-interface to Scilab split into four sub-sections: query, access, creation of objects, and miscellaneous functions.
All C-interface functions are introduced in SCI/routines/stack-c.h.
The functions in this group retrieve information about the parameters a function has been called with, and about the properties of objects on the stack.
function CheckRhs (MinNumParameter : in Natural; MaxNumParameter : in Natural) return Integer;
Check the number of actual parameters on the right-hand side to be in the range MinNumParameter : MaxNumParameter. Return 1 if it is in the range, otherwise raise error 77 associated with the name of the C-function from which CheckRhs is called.
The semantics of CheckRhs is slightly goofy. If the number of actual input parameters is in the specified range, CheckRhs returns 1, but it never returns 0 as it raises an error in this case. Therefore, the return value can safely be ignored, as we do in the Example.
int myfun(const char *fname) { /* local variables */ CheckRhs(1, 1); -- check for exactly one argument /* more code goes here */ }
function CheckLhs (MinNumParameter : in Natural; MaxNumParameter : in Natural) return Integer;
Check the number of actual parameters on the left-hand side to be in the range MinNumParameter : MaxNumParameter. Return 1 if it is in the range, otherwise raise error 78 associated with the name of the C-function from which CheckLhs is called.
The semantics of CheckLhs is slightly goofy. If the number of actual output parameters is in the specified range, CheckLhs returns 1, but it never returns 0 as it raises an error in this case. Therefore, the return value can safely be ignored, as we do in the Example.
Note that a seemingly empty left-hand side as in
-->ones(2,3) ans = ! 1. 1. 1. ! ! 1. 1. 1. !
implies the variable ans, and accordingly the number of left-hand side parameters in this case is 1.
int myfun(const char *fname) { /* local variables */ CheckLhs(1, 1); -- allow a maximum of one return value /* more code goes here */ }
function Lhs : Natural;
The number of actual output parameters, i.e. those on the left-hand side of the assignment operator, is available through Lhs.
Note that a seemingly empty left-hand side as in
-->ones(2,3) ans = ! 1. 1. 1. ! ! 1. 1. 1. !
implies the variable ans, and accordingly the number of left-hand side parameters, Lhs, in this case is 1.
function GetType (ParameterNumber : in ParameterStackIndex) return TypeCode;
Inquire the Scilab type code of argument ParameterNumber. The type codes are the same as returned by type. The first parameter has index 1. See Table 4-3 for a complete listing of all available type codes.
int vandermonde(const char *fname) { /* local variables */ CheckRhs(1, 1); -- assert one argument if (GetType(1) != 1) { -- test for a float Scierror(814, "%s: expecting floating point entity", fname); return 1; } /* more code goes here */ }
The following functions allow for the access of the Scilab data stack, and the mapping of C-pointers to and from stack indices.
Please remember that variables of type ParameterStackAddress, within the user function, point to unique stack positions. Thus, after the calls
GetRhsVar(1, "d", &rows1, &cols1, &idx1); CreateVar(1, "d", &rows2, &cols2, &idx2); /* Ouch! */
stk(idx1) and stk(idx2) point to the same memory location. Sometimes – if and only if the "old" variable is not accessed anymore – this is desired.
The type of a variable on the stack, whether it is the actual type of an argument passed in, or the requested type of a local variable, is defined with a string of length 1, the TypeString. All valid type strings a compiled in Table 7-4.
Table 7-4. TypeString Identifiers
TypeString | C or Scilab type |
---|---|
S | string |
c | single precision complex, struct complex { float re, im; } (see also Section 7.2.2) |
d | double |
f | float |
i | int |
l | list |
p | void* |
r | reference? |
t | tlist |
z | double precision complex, struct double_complex { double re, im; } (see also Section 7.2.2) |
procedure GetRhsVar (ParameterNumber : in ParameterStackIndex; VariableType : in TypeString; Rows : out AccessNatural; Columns : out AccessNatural; StackIndexPtr : out AccessDataStackIndex);
Return size and Scilab-stack address of function argument number ParameterNumber. The argument must have type VariableType. See Table 7-4 for valid type-strings.
On success Rows and Columns hold the dimensions of the parameter (twice a one for a scalar) and StackIndexPtr points to the index of start address of the parameter on the Scilab stack stk.
GetRhsVar performs weak type checking with respect to VariableType. If VariableType = "d" and a (double) complex is passed to the function, no error is raised! Integers, strings, etc. do raise an error in this case. Therefore, the type of an argument always should be inquired with GetType before calling GetRhsVar.
int vandermonde(const char *fname) { int rows, cols, vec_idx; double *input_vec; /* more code */ GetRhsVar(1, -- get first argument "d", -- expect double &rows, -- number of rows &cols, -- number of columns &vec_idx); -- stack index if (rows != 1 && cols != 1) { Scierror(815, "%s: expecting vector", fname); return 1; } input_vec = stk(vec_idx); -- convert index to pointer /* more code */ }
procedure GetMatrixptr ( );
FIXME: Write it!
...
...
procedure GetRhsCVar ( );
FIXME: Write it!
...
...
procedure GetFuncPtr ( );
FIXME: Write it!
...
...
LhsVar : array (ParameterStackIndex) of ParameterStackIndex;
LhsVar is an array of the return values of a function. Assigning to LhsVar (N) means assigning to return-value number N. The values put into LhsVar are the numbers of local variables, which have previously been created with CreateVar or GetRhsVar.
int vandermonde(const char *fname) { int rows, cols, vec_idx; int n, vdm_idx; double *input_vec; double *vdm_matrix; /* some code here */ GetRhsVar(1, -- argument 1 at stack position 1 "d", &rows, &cols, &vec_idx); input_vec = stk(vec_idx); n = (rows > cols) ? rows : cols; /* allocate matrix */ CreateVar(2, -- local variable 1 at stack position 2 "d", &n, &n, &vdm_idx); /* compute Vandermonde matrix */ LhsVar(1) = 2; -- stack position 2 goes to return-value 1 return 0; }
The line LhsVar(1) = 2; requires further explanation. The left-hand side of the assignment specifies the first element in the array of all return values of the function. The right hand side of the assignment denotes the first local variable (created with CreateVar in the example) within the function. It has stack index 2, because this is the first free stack position after all parameters (here: 1).
The functions in the create group of the core interface allocate new Scilab variables on the Scilab data stack, which are accessed through their index on the parameter stack.
procedure CreateVar (VariableNumber : in ParameterStackIndex; VariableType : in TypeString; Rows : in AccessNatural; Cols : in AccessNatural; StackIndex : out AccessDataStackIndex);
Create a new local Scilab variable on the Scilab stack. The variable is later accessed with its "handle", VariableNumber. The type of the variable is selected with VariableType. See Table 4-3 for a complete listing of all type codes. The size of the new scalar, vector, or matrix is determined by Rows, and Cols. Scalars have Rows := 1; Cols := 1.
On return the CreateVar sets StackIndex to the element in the data stack stk that points to the start address of the newly created variable.
int vandermonde(const char *fname) { int vdm_idx; const int n = 4; double *vdm_matrix; /* some code here */ CreateVar(2, -- first local variable "d", -- double precision &n, -- n rows &n, -- n columns &vdm_idx); -- index into stack vdm_matrix = stk(vdm_idx); -- convert to pointer /* more code here */ }
procedure CreateVarFromPtr ( );
FIXME: Write it!
...
procedure WriteMatrix (ScilabVariableName : in String; Rows : in ConstAccessNatural; Cols : in ConstAccessNatural; Carray : in ConstAccessAny);
FIXME: Write it!
send array C[] to Scilab as variable C; see: intex14c.c
...
...
procedure WriteString (ScilabVariableName : in ConstAccessString; CstringLength : in ConstAccessNatural; Cstring : in ConstAccessString);
FIXME: Write it!
create the Scilab variable Str from str; see: intex16c.c
...
...
The dreaded miscellaneous... All functions that do not fit in any of the above categories go here.
procedure Scierror (ErrorNumber : Natural; FormatString : String; FunctionName : String);
Raise error ErrorNumber, associated with the errors message FormatString, which is preceeded by the function's (the one we are currently in) name FunctionName.
int hrtimer(const char *fname) { /* code left out here */ if (t < 0.0) { Scierror(5771, "%s: internal error\n", fname); return 1; } /* code left out here */ }
procedure PExecSciFunction ( );
FIXME: Write it!
From the example file: Executes the Scilab function (f) pointed to by sci_f. We provide a rhs = 2 and expect lhs = 1; PExecSciFunction(5, &sci_f, &lhs, &rhs, "ArgFex", ex17cenv);
intex17c.c ...
procedure ReadString (Identifier : in ConstAccessString; CstringLength : in out AccessNatural; Cstring : out AccessString);
Form the example file: We search a Scilab object named Mystr check that it is a string and store the string in str. strl is used on entry to give the maximum number of characters which can be stored in str. After the call strl contains the number of copied characters.
intex15c.c ...
procedure SciFunction ( );
FIXME: Write it!
execute the function; SciFunction(&ibegin, &lf, &mlhs, &mrhs);
intex8c.c ...
procedure SciString ( );
FIXME: Write it!
eval()? exec()? SciString(&ibegin, name, &mlhs, &mrhs);
intex7.c.c, intex11c.c, intex12c.c ...