MATLAB Coder: Make the Function Codegen-Ready Before You Build
MATLAB Coder compiles a subset of MATLAB, so the real work is making a function statically typed and bounded before you touch build flags.
20 Jan 2026, 18:37 UTC

The error that stops most first attempts
You have a MATLAB function that runs correctly in the interpreter. You point codegen at it and get an unsupported-function error, or a size mismatch on a variable that was never a problem before. The instinct is to start adjusting build flags. That is usually the wrong first move.
MATLAB Coder does not translate arbitrary MATLAB. It compiles a statically analyzable subset, and the real work is rewriting the function so that every variable has a known class and a known or bounded size at every point in the program. Once that is true, the build configuration is a short command.
What code generation actually requires
Three constraints account for most failures.
- Class stability. A variable cannot be
doubleon one branch andlogicalon another. Preallocate with the intended type up front, for examplezeros(n,1,'like',x). - Size determinism. Every array needs a fixed size or an upper bound the generator can prove. Unbounded inputs become dynamically allocated
emxArraystructures in the generated C. That is acceptable for a desktop DLL and often unacceptable on a microcontroller with no heap. - No dynamic dispatch.
eval, dynamic field names, most function handles, Java objects and many toolbox class objects fall outside the supported set.
The supported-function list is release-specific. Check the "Functions and Objects Supported for C/C++ Code Generation" documentation page for the MATLAB version you are actually building with, rather than trusting any summary of it, including this one.
Two tools that tell you where you stand
Add %#codegen as a comment line inside the function. It does nothing at run time; it makes the MATLAB editor flag constructs that code generation will reject, so you find them while writing instead of at build time.
For an existing file, coder.screener('myFunction') produces a readiness report listing unsupported calls and the lines that use them. Run it from the MATLAB command window with the function on the path. Treat the report as a to-do list rather than a verdict: some flagged items are harmless if that branch is never reached from your entry point.
A worked example: a bounded moving average
Consider a causal moving average. The naive version slices x(lo:k), which creates a variable-size array inside the loop and forces the generator to reason about dynamic sizing.
function y = movingMean(x, window)
%#codegen
% x: real row vector, window: positive integer scalar
n = numel(x);
assert(n <= 1024); % upper bound the generator can use
assert(window >= 1 && window <= n);
y = zeros(size(x), 'like', x);
acc = 0;
for k = 1:n
acc = acc + x(k);
if k > window
acc = acc - x(k - window);
end
if k < window
y(k) = acc / k;
else
y(k) = acc / window;
end
end
end
The running accumulator removes the slice, and the assert statements give the generator a provable bound on n. MATLAB Coder honors assert for size and class inference, so the bound does not need to be repeated in the build command.
Build a MEX first. It is the fastest way to check numerical agreement without leaving MATLAB. Run this from the MATLAB command window, with the function on the path and write permission in the current folder:
codegen -config:mex movingMean -args {coder.typeof(0,[1 1024],[0 1]), coder.typeof(0,[1 1])} -report
coder.typeof(0,[1 1024],[0 1]) describes a real row vector whose first dimension is fixed at 1 and whose second is variable up to 1024. The -report flag opens the code generation report, which lists the generated files and any remaining issues. The MEX is written to the current folder as movingMean_mex.
Compare the two implementations on the same input:
x = randn(1, 500);
yRef = movingMean(x, 8);
yMex = movingMean_mex(x, 8);
max(abs(yRef - yMex))
The difference should be at or near double-precision round-off. If it is not, the loop logic changed during translation, so check the report before blaming the compiler. This comparison is one you run yourself; the actual numbers depend on your input and your release.
Once the MEX agrees, switch to the deployment target: -config:lib for a static library plus header, -config:dll for a shared library, or -config:exe for a standalone executable with a generated main. Generated .c and .h files land in the output folder, which defaults to codegen/lib/movingMean for a library build.
Where this approach costs you
Generated C is not hand-tuned C. For tight inner loops, a careful C implementation with explicit SIMD or fixed-point arithmetic will usually beat the generated version, and the gap widens when the generator falls back on dynamic allocation for unbounded inputs. If your target has no heap, bound every input or the build will not link cleanly.
There is also a licensing and version dimension. MATLAB Coder requires its own license in addition to MATLAB, and support for a given toolbox function can change between releases. Fixed-point and processor-specific optimizations live in Embedded Coder, a separate product.
What to do next
- Run
coder.screeneron the function you intend to deploy and resolve the unsupported calls. - Add
%#codegenand rewrite loops so array sizes are fixed or asserted. - Build a MEX and compare its output against the interpreted function on representative inputs, including edge cases such as
window = 1andwindow = n. - Only then choose
-config:lib,-config:dllor-config:exeand integrate the generated header into your C project.
When a step fails, the code generation report is the first place to look. It names the line and the reason, which is far more useful than the summary error printed in the command window.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.