Friday, April 19, 2019

Accessing workspace from C-Mex s-function

In Matlab Simulink you can access workspace variables from a C-Mex (C++/C) s-function as follows:



/*Demo for getting workspace variables from C-Mex s-function*/
#define S_FUNCTION_NAME getInputs
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
static void mdlInitializeSizes( SimStruct *S ) {
printf("\nHello from getInputs.cpp, mdlInitializeSizes()\n");
if ( !ssSetNumOutputPorts( S, 2 ) ) return;
ssSetOutputPortWidth( S, 0, 1 ); // mass_kg
ssSetOutputPortWidth( S, 1, 3 ); // position_m
}
void setOutputPortReal(SimStruct *S, int iPort, double value) {
double *out = (double *)ssGetOutputPortRealSignal(S, iPort);
out[0] = value;
}
void setOutputPortRealVector3(SimStruct *S, int iPort, double* values) {
double *out = (double *)ssGetOutputPortRealSignal(S, iPort);
for (int i = 0; i<3; i++) {
out[i] = values[i];
}
}
double* getVectorFromWorkspace(char* varName) {
const mxArray* varPtr = mexGetVariablePtr("base", varName);
double* vals = mxGetPr(varPtr);
return vals;
}
double getDoubleFromWorkspace(char* varName) {
double* vals = getVectorFromWorkspace(varName);
return vals[0];
}
#define MDL_INITIALIZE_CONDITIONS
static void mdlInitializeConditions( SimStruct *S ) {//Invoked at the beginning of simulation.
printf("\nHello from getInputs.cpp, mdlInitializeConditions()\n");
setOutputPortReal(S, 0, getDoubleFromWorkspace("mass_kg"));
setOutputPortRealVector3(S, 1, getVectorFromWorkspace("position_m"));
}
static void mdlOutputs( SimStruct *S, int_T tid ){ //Invoked at each simulation time step (not just major time steps)
printf("\nHello from getInputs.cpp, mdlOutputs()\n");
}
/*Obligatory Simulink code*/
static void mdlInitializeSampleTimes(SimStruct *S) {}
#define MDL_START
#if defined(MDL_START)
static void mdlStart(SimStruct *S) {}
#endif /* MDL_START */
#define MDL_UPDATE
static void mdlUpdate( SimStruct *S, int_T tid ) {}
static void mdlTerminate( SimStruct *S ) {
UNUSED_ARG(S); /* unused input argument */
}
#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif
view raw getInputs.cpp hosted with ❤ by GitHub
To write to workspace from C-Mex, you can use
#include "matrix.h"
...
mxArray* pa = mxCreateDoubleScalar(12.34);
mexPutVariable("base", "myVarName", pa);

Note that you cannot use myVarName in a simulink block unless you call it before or during InitFcn.

No comments: