I have a Simulink model that I need to execute from within Python. I have been using C code generated with NI VeriStand to compile a Linux shared library that allows me to execute my simulation from within Python.
One of the things I want to do is save the state of my simulation (i.e., continuous and discrete variables, and clock ticks). The C source exported by VeriStand provides a function called NIRT_GetSimState for such a purpose.
DLL_EXPORT int32_t NIRT_GetSimState(int32_t* numContStates, char * contStatesNames, double* contStates, int32_t* numDiscStates, char
* discStatesNames, double* discStates, int32_t* numClockTicks, char
* clockTicksNames, int32_t* clockTicks)
{
int32_t count = 0;
int32_t idx = 0;
if ((numContStates != NULL) && (numDiscStates != NULL) && (numClockTicks !=
NULL)) {
if (*numContStates < 0 || *numDiscStates < 0 || *numClockTicks < 0) {
*numContStates = 1;
*numDiscStates = 0;
*numClockTicks = NUMST - TID01EQ;
return NI_OK;
}
}
if ((contStates != NULL) && (contStatesNames != NULL)) {
idx = 0;
contStates[idx] = NIRT_GetValueByDataType(&(electric_motor_X.speed), 0, 0, 0);
strcpy(contStatesNames + (idx++ * 100), "speed");
}
if ((clockTicks != NULL) && (clockTicksNames != NULL)) {
clockTicks[0] = S->Timing.clockTick0;
strcpy(clockTicksNames, "clockTick0");
}
UNUSED_PARAMETER(count);
UNUSED_PARAMETER(idx);
return NI_OK;
}
I have been trying to find a way to use this function in Python, as loaded from a shared library.
from ctypes import *
self._model = CDLL(model_lib)
self._lib_get_state = self._model.NIRT_GetSimState
I want to find a way to pass the correct data types to the function in Python. From what I understand, I need to pass pointers to integers and to arrays.
I am using the following function for testing. I am creating variables and arrays using ctypes.
def _get_state(self):
numContStates = c_int(-999)
contStatesNames = (c_wchar_p*1)('a')
contStates = (c_double*1)(-999.99)
numDiscStates = c_int(-999)
discStatesNames = (c_wchar_p*1)('a')
discStates = (c_double*1)(-999.99)
numClockTicks = c_int(-999)
clockTicksNames = (c_wchar_p*1)('a')
clockTicks = (c_int*1)(-999)
self._lib_get_state(byref(numContStates), byref(contStatesNames), byref(contStates), byref(numDiscStates), byref(discStatesNames),
byref(discStates), byref(numClockTicks), byref(clockTicksNames), byref(clockTicks))
print('Number of continuous states: ', numContStates.value)
print('Number of discrete states: ', numDiscStates.value)
print('Number of clock ticks: ', numClockTicks.value)
print('Names of continuous states: ', list(contStatesNames)) # Expecting ['speed']
print('Values of continuous states: ', list(contStates)) # Expecting [0.0]
I seem to be getting the right values for the number of discrete and continuous states but the arrays with the continuous states and their names are not updated. This is what the function prints:
Number of continuous states: 1
Number of discrete states: 0
Number of clock ticks: 1
Names of continuous states: ['a']
Values of continuous states: [-999.99]
So, we can see that the function call did not update the arrays. I think that I'm probably not using the right data types to call the function. This is my first time using ctypes.
Could someone confirm if there is a mistake in the data types? and what the correct syntax should be?
Thank you.