Simulink embedded Matlab functions: Headerless coder.cinclude() for custom C/C++ functions
It’s well-known that you can use coder.ceval(...)
in in conjunction with coder.cinclude(...)
to run external C/C++ functions from embedded matlab functions:
function y = mysquare(x) %#codegen
coder.cinclude('mysquare.h');
y = 0.0;
coder.ceval('mysquare', coder.ref(x), coder.wref(y));
end
What’s less known is that you an include C/C++ code “inline” in the coder.cinclude()
call, albeit this is somewhat contrived. This is very helpful so you don’t have to manage header files.
Note that when compiling your model, Simulink/Matlab coder still needs to check if it compiles properly, so you need to ensure that “standalone” compilation of your code is possible.
function y = mysquare(x) %#codegen
% Using coder.cinclude() just means it will be included at the top of the
% file, hence we can misuse it to include the entire function instead of
% just the header include.
coder.cinclude(sprintf(...
['<math.h>\n' ... % Dummy include to terminate the #include line
'inline void mysquare(const double* x, double* y) {\n' ...
' *y = (*x) * (*x);\n' ...
'}'] ...
));
y = 0.0;
coder.ceval('mysquare', coder.ref(x), coder.wref(y));
end
Remember that it’s absolutely essential to use the dummy <math.h> include to terminate the #include line!
This will generate the following code in the header file:
#include <math.h>
inline void mysquare(const double* x, double* y)
{
*y = (*x) * (*x);
}
and, with sufficient comment levels turned on, this is the code from the generated .cpp
file
/* MATLAB Function 'Logic/S-Process emulation/MATLAB Function1': '<S7>:1' */
/* '<S7>:1:5' coder.cinclude(sprintf(... */
/* '<S7>:1:6' ['<math.h>\n' ... % Dummy include to terminate the #include line */
/* '<S7>:1:7' 'inline void mysquare(const double* x, double* y) {\n' ... */
/* '<S7>:1:8' ' *y = (*x) * (*x);\n' ... */
/* '<S7>:1:9' '}'] ... */
/* '<S7>:1:10' )); */
/* '<S7>:1:11' y = 0.0; */
/* '<S7>:1:12' coder.ceval('mysquare', coder.ref(x), coder.wref(y)); */
mysquare(&rtb_y_l, &rtb_y);