Emulate Object Oriented in Scilab - part 3
The current version of the Scilab language is procedural. The goal of this page is to show how to make a OO-like system in Scilab, based on the SCILAB_POINTER_DATATYPE data type.
That method has been re-discovered by Antoine Elias recently. Apparently, it was developped to create an interface for sparse linear algebra. I made some modifications to the source code produced by Antoine to meet my needs to emulate OO in Scilab.
See in attachment scipointer-v0.2.zip for a .zip which contains the full toolbox, validated on Windows.
On the use of Scilab pointers
I make the hypothesis that I have a C++ class, "MyClass", which has 3 members : type, a, b and possess a "print" method. The goal is to be able to write in the Scilab console :
vu1 = myclass_new("Normale",1.0,0.5); myclass_print(vu1); myclass_destroy(vu1);
At the core of the method is the Scilab data type SCILAB_POINTER_DATATYPE. To create such a variable, one simply use the CreateVarFromPtr function, extracted from sci_myclass_new.cpp :
myobject = new MyClass(name, parameter1, parameter2); CreateVarFromPtr(Rhs + 1, SCILAB_POINTER_DATATYPE , &iRows, &iCols, (void*)myobject); /* Note that this code is deprecated and should be replaced by API_Scilab */
When the print method is to be called, on first get a pointer to the location in the stack where the real pointer is stored. Then, one cast back the pointer into the real class data type. This is done in the following source code, extracted from sci_myclass_print.cpp :
GetRhsVar(1, SCILAB_POINTER_DATATYPE, &iRows, &iCols, &iStackPointer); /* Note that this code is deprecated and should be replaced by API_Scilab */ myobject = (MyClass*)((unsigned long int) *stk(iStackPointer)); myobject->Print();
The destructor is based on the same method, but, this time, the "free" command is called. The following source code is extracted from sci_myclass_destroy.cpp :
GetRhsVar(1, SCILAB_POINTER_DATATYPE, &iRows, &iCols, &iStackPointer); /* Note that this code is deprecated and should be replaced by API_Scilab */ myobject = (MyClass*)((unsigned long int) *stk(iStackPointer)); free(myobject);
The following script shows how to use these methods from the Scilab language :
vu1 = myclass_new("Normale",1.0,0.5); // Look in the real console ! (F12 under Windows) myclass_print(vu1); myclass_destroy(vu1);
There is no difficulty to create the gateways.
The following is a list of advantages / drawbacks.
- it is possible to manage C++ objects in the Scilab language.
- the system does not require a lot of memory. Just the address of the object is stored.
- the system is simple.
the automatic completion gives rich informations. With the current method, type "myclass" + <TAB> in the console and you get the complete list of methods which are associated with the class "myclass".
- there is no need to encapsulate the class : it can be directly accessed without any modification.
- there is no verification of type.
Suppose that two objects are implemented with this method, say "a" for "myclass" and "b" for "mybetterclass". Now, if you pass the token "b" to a method of the class "myclass", it is very probable that the integer a will index an existing position in the hash map, i.e. the method will have an unexpected effect, but will not generate an error. Respectively, it may index a position which does not exist. That may lead to bugs difficult to analyse.