A Pointer Transfer Between the S-functions
- Technology:
- Simulink S-function level 2, C++
- Tested:
- Linux Matlab Version 7.0.4 (R14SP2), Simulink Version 6.2 (R14SP2)
- Windows Matlab Version 6.5.1 (R13SP1), Simulink Version 5.1 (R13SP1)
- Keywords:
- Matlab, Simulin, S-function, cpp, user data type, pointer transfer between S-functions
Here is described S-function example, which transfers a pointer to an object from one Simulink block to others Simulink blocks. Pointer is marked as your own Simulink data type, which is more safety for a data mismatch.
This example consists from four files. First one (sfun_source.cpp) sends a pointer to a class 'my_class' (defined in the file myclass.h). This class includes one double which is read from the input, but in general it can include something. Third file (sfun_destination.cpp) is receiver, which read the pointer and returns the double number which is inside of the object. Simulink data type is defined in the file datatype_myclass.cpp.
Code Notes
Simulink custom data type registration, consists from three steps (example from datatype_myclass.cpp).
- Data type name registration:
DTypeId data_type_id = ssRegisterDataType(S, "MyClass");
- Specify the amount of memory. If you set the size of a custom data type, you must set a size which is same as a size of double data type. This is very significant, because the pointer to 'my_class' must be during transferring retyped to the double data type. If you use a smaller size, than is double size you lost pointer.
double tmpdouble;
ssSetDataTypeSize(S, data_type_id, sizeof(tmpdouble)); - Specify the value that represents a zero value. There is necessary use as zero representation any instance of your object. Interesting is that your object must include a constructor, which set a value to your variables inside the object. Otherwise you receive error: cannot modify the zero representation of data type 'MyClass'.
MyClass* var_myclass = new MyClass;
ssSetDataTypeZero(S, data_type_id, var_myclass);
After user data type registration you can sends the pointer in mdlOutputs callback function:
y[0] = (long int)var_myclass;
Important is the second line, where data type pointer to MyClass, is firstly converted to the data type long int, and next automatically to the double (respective to rel_T).
For back conversion to the pointer we can use next commands. In most case placed in the mdlUpdate callback function in others Simulinks blocks.
MyClass *var_myclass = (MyClass*)((long int)(*u[0]));
You can download this entire example
. Simulink mdl file with example is there too.
Question and unsolved problems:
- Why must object include a constructor which set any value to the objects variables?
- Where is removed the object for zero representation from memory? I don't know where I can call delete command.
- How convert safety a pointer data type to the double? Command used above is working, but it isn't good with respect to rounding error. Second idea is copy number bit to bit from the pointer to the double by this command: memcpy(&variable, &object, sizeof(object)). I never try it, but theoretically there are problems too.
- I can't register user data type with name 'myclass', do anybody why?
If you know the answer to any of these questions, have you got any commentary, or you don't understand something, please send me email to kutilm@fel.cvut.cz.
Note: In this example aren't solved exceptions and other problems which aren't in direct relation to the problem described above.
Thanks to Michal Sojka and Brad Phelan for hints and consultations.