---
name: matlab/matlab-generate-code
source: https://app.decimal.ai/s/matlab-matlab-generate-code@1/SKILL.md
source_sha256: b7bf675cf8de
---

# Generate Code with MATLAB Coder

Umbrella skill for the MATLAB Coder workflow: generate code, verify it, refine the config, and accelerate with profiled MEX.

## When to Use

- Generating C/C++ or CUDA code from MATLAB functions (MEX, lib, dll, exe)
- Writing new MATLAB code that must be compatible with code generation
- Reviewing existing MATLAB code for codegen readiness or fixing codegen errors
- Configuring codegen settings for specific targets (embedded, speed, readability, safety)
- Verifying generated code matches MATLAB output (coder.runTest, matlabtest.coder.TestCase)
- Profiling and accelerating generated MEX functions
- Using coder.* directives (coder.varsize, coder.const, coder.extrinsic, coder.ceval, etc.)

## When NOT to Use

- Simulink Coder / Embedded Coder Simulink-model workflows
- Generating code for target languages that are not C, C++, or CUDA
- Fixed-Point Designer conversion workflows
- Hand-written MEX C files (not generated by MATLAB Coder)
- General MATLAB programming unrelated to code generation

### Route to a more specific skill

- **Generating code from an AI model** (PyTorch `.pt2` / LiteRT `.tflite` via `loadPyTorchExportedProgram` / `loadLiteRTModel`) → use **matlab-deploy-ai-model**. Return here for the underlying `coder.*` directives, config tuning, and screener/verification.
- **Deploying to physical embedded hardware** (on-target PIL, ERT hardware configs, board selection — STM32 / Raspberry Pi / ARM Cortex) → use **matlab-deploy-embedded-code**. This skill covers host-side codegen, SIL, and config tuning up to hardware targeting.
- **Speeding up interpreted MATLAB by rewriting the M-code** (vectorization, preallocation, caching) → use **matlab-optimize-performance**. This skill's acceleration path assumes you want to compile to MEX/C, not restructure the algorithm.
- **General MATLAB test authoring** (parameterized tests, fixtures, mocking, coverage, CI/CD, App Designer) → use **matlab-testing**. This skill covers only codegen-equivalence tests (`coder.runTest`, `matlabtest.coder.TestCase`).
- **Modernizing deprecated APIs for currency/maintainability** when code generation is not the goal → use **matlab-modernize-code**. This skill rewrites source only to satisfy codegen constraints, with explicit authorization.

## Routing — load the matching reference file on demand

Pick the workflow that matches the user's intent and read the corresponding `references/*.md`. Each reference file is a deep, self-contained guide; load only what you need rather than carrying all four in context.

| User intent | Load |
|---|---|
| Writing new codegen-compatible MATLAB; reviewing MATLAB for codegen readiness; fixing codegen errors; `%#codegen`; language constraints; type/size rules | `references/write-codegen-ready.md` |
| Understanding a specific `coder.*` directive (coder.varsize, coder.const, coder.inline, coder.unroll, coder.extrinsic, etc.) | `references/write-coder-directives.md` |
| Using MATLAB classes in codegen; class limitations; `coder.classSignature`; handle vs value class restrictions | `references/write-class-limitations.md` |
| Generate C/C++/CUDA code (MEX, lib, dll, exe), specify input types, fix `coder.screener` issues | `references/generate-code.md` |
| Verify generated code matches MATLAB; write `coder.runTest` / `matlabtest.coder.TestCase` tests; SIL setup | `references/verify-code.md` |
| Tune a working config for a deployment goal (embedded / speed / readability / size / safety) | `references/refine-config.md` |
| Profile generated MEX, measure `coder.timeit` / `coder.perfCompare`, find hotspots | `references/accelerate-mex.md` |
| Look up a config property's name, availability, or non-obvious behavior | `references/config-properties.md` |

**Disambiguation — "write" vs. "generate" vs. "generate for a class":**
- "Write codegen-ready code" = authoring/reviewing the MATLAB source so it *can* be compiled (`write-codegen-ready.md`)
- "Generate code" = running `codegen` to produce C/C++ from an already-valid function (`generate-code.md`)
- "Generate code for a class" / "generate C++ class" = the user's source is a `classdef` file → load `generate-code.md` (Step 0 handles class entry points via `coder.ClassSignature`). Do NOT default to wrapping the class in a function.
- If both apply (user wants to write a function AND generate code from it), load `write-codegen-ready.md` first, then `generate-code.md`

For requests that span workflows (e.g., "generate MEX, verify it, then speed it up"), load the references in order rather than all at once.

## Out of scope

- **Simulink** Coder / Embedded Coder workflows (these are skill candidates of their own).
- **Non-C, C++, or CUDA target languages** — this skill covers C/C++ and CUDA code generation only
- **Fixed-point conversion** (use Fixed-Point Designer).
- **Hand-written MEX files** — the acceleration guidance assumes MATLAB Coder-generated MEX.
- **`CodeExecutionProfiling` / SIL profiling** with Embedded Coder — out of scope for the acceleration reference.

## Cross-cutting rules

These apply across every workflow. Apply them whether or not you've loaded a per-workflow reference yet.

### Class entry point — use `coder.ClassSignature`, not a wrapper function

When the user's target is a MATLAB class (classdef file) and they want to generate C++ code from it, use `coder.ClassSignature` for direct class code generation. Do NOT create a wrapper entry-point function. This produces a proper C++ class with methods — which is what users mean when they say "generate C++ class."

Load `references/generate-code.md` → Step 0 and `references/write-class-limitations.md` → "Direct class code generation" for the full workflow. The prerequisite `enableCodegenForEntryPointClasses` must run once per session.

Only fall back to a wrapper function if the user's MATLAB version lacks `coder.ClassSignature` (pre-R2026a) or the class structure is incompatible (e.g., handle objects in entry-point I/O).

### Ask for input types before writing codegen-ready functions

Before writing any new codegen-ready function, ask the user:
- Data type of each input (double, single, int32, uint8, logical, struct, etc.)
- Size/shape (scalar, fixed-size vector/matrix, variable-size with bounds?)
- Real or complex?

Do NOT ask about variable-size upper bounds unless the user has explicitly requested DMA-off (no dynamic memory) code generation. See `references/write-codegen-ready.md` for full authoring guidance.

### One variable, one type, one size category

A variable cannot change class or complexity after first assignment. This is the #1 source of codegen errors in practice. Assign different-sized values on different branches only after declaring `coder.varsize`. See `references/write-codegen-ready.md` for the full constraint list.

### Always capture `coder.screener` output — every time

```matlab
res = coder.screener('myFunction');   % NOT bare: coder.screener('myFunction')
disp(res.UnsupportedCalls)
disp(res.Messages)
```

Bare `coder.screener('func')` opens the GUI with no command-line output. **Always** assign the return value, then inspect `UnsupportedCalls` and `Messages`.

This rule applies to every reference to `coder.screener` you write — including summaries, status updates, and commentary, not just the actual call you execute. Don't write `coder.screener('myFunction')` as a bare phrase even when describing what you did; mirror the assignment-syntax form (or just refer to "the screener" prose-style). A bare call in a summary suggests the user should reproduce it that way.

### Verify with MEX before generating lib / dll / exe

Generate MEX first and compare its output to the interpreted MATLAB. Once MEX matches, generate the standalone target. Comparing two interpreted MATLAB runs proves nothing — and aggressive optimizations on lib/dll can mask bugs that surface only in the deployed code path.

### Never modify the user's source without authorization

The user's MATLAB source is theirs. Even when `coder.screener` flags an unsupported call or construct, do not silently rewrite the source — present a short summary of the proposed change (which lines, what's removed/replaced, why) and wait for the user to confirm before applying. This applies whether the change is a one-line guard around a `try`/`catch`, a swap of `containers.Map` for a struct, removal of an `eval`, or a tightened `arguments` block. The same rule applies when a codegen error suggests a source-level fix.

Trivial mechanical changes still need the same confirmation step. The one exception is a copy of the source into a private working directory for codegen experiments; that copy may be edited freely as long as the original file is untouched.

### Booleans are `logical`, not char

Every `Enable*` and similar config property takes `true` / `false`. Never `'On'` / `'Off'`. Use `class(cfg.PropName)` if unsure.

### Don't add report flags unless the user asks

Do not pass `-report`, `-launchreport`, or set `GenerateReport = true` unless the user explicitly requests a code-generation report.

### Use function-call syntax for variable paths

```matlab
% YES — function-call syntax evaluates the variable
outDir = fullfile(pwd, 'codegen_output');
codegen('myFunction', '-config', cfg, '-args', {t1, t2}, '-d', outDir)

% NO — command syntax can take "outDir" as a literal directory name
codegen -config cfg myFunction -args {t1, t2} -d (outDir)
```

### Introspect the live config object

Property names, defaults, and per-config-type availability drift across MATLAB releases. Before recommending settings, query the user's actual config:

```matlab
cfg = coder.config('lib');     % or 'mex', or coder.gpuConfig(...)
class(cfg)                     % CodeConfig vs. EmbeddedCodeConfig vs. MexCodeConfig
properties(cfg)                % full property list for this version
disp(cfg)                      % current values
isprop(cfg, 'EnableMemcpy')    % does a candidate property exist?
```

Treat the live introspection — not memory of past releases — as ground truth. See `references/config-properties.md` for more.

## Quick Reference — Coder Directives

| Directive | Purpose | Key gotcha | Available From |
|-----------|---------|-----------|---------------|
| `%#codegen` | Enable codegen analysis | Must be on/after function signature | R2011a |
| `coder.typeof(val, sz, varDims)` | Define input type+size for codegen call | `varDims` is logical array — `true` = variable | R2011a |
| `coder.varsize('x', [bounds])` | Declare variable-size with upper bounds | Without bounds → requires DMA; declare before first assignment | R2011a |
| `coder.const(expr)` | Evaluate expr at compile time | Expression can be arithmetic, a function call, or a combination | R2013b |
| `coder.extrinsic('fn')` | Exclude function from compilation | No-op in lib/dll/exe unless paired with `coder.const` | R2011a |
| `coder.inline('always'\|'never')` | Control function inlining | Use `'always'` for small hot helpers | R2011a |
| `coder.unroll(range)` | Unroll loop at compile time | Required for heterogeneous cell / varargin iteration | R2011a |
| `coder.noImplicitExpansionInFunction` | Disable broadcasting overhead | Only when operands always match in size | R2021b |
| `coder.target('MATLAB')` | Branch between MATLAB and codegen paths | Inactive branch is eliminated from generated code | R2011a |
| `coder.nullcopy(zeros(m,n))` | Allocate without zeroing | Only safe if every element is written before read | R2011a |
| `coder.ClassSignature` | Direct class code generation entry point | Requires `enableCodegenForEntryPointClasses` once per session | R2026a |

For full directive documentation, load `references/write-coder-directives.md`.

## Common Mistakes

| Mistake | Correct Approach |
|---------|-----------------|
| `coder.screener('func')` without capturing return value | `res = coder.screener('func')` then inspect `res.UnsupportedCalls` and `res.Messages` |
| Jumping straight to lib / dll without MEX verification | Generate MEX first, compare outputs to MATLAB, then generate the final target |
| `EnableRecursion` (does not exist) | `EnableRuntimeRecursion` |
| `DynamicMemoryAllocation = 'Off'` | `EnableDynamicMemoryAllocation = false` (logical, not char) |
| `MemcpyThreshold = 0` to disable memcpy | `EnableMemcpy = false` |
| Comparing two interpreted MATLAB runs to "verify" generated code | Use `coder.runTest` (MEX replacement) or `matlabtest.coder.TestCase`; or SIL with Embedded Coder |
| `coder.timeit(@myFunction, ...)` (function handle) | `coder.timeit('myFunction', numOutputs, {args})` — string name |
| Profiling the interpreted MATLAB function instead of the MEX | Profile `myFunction_mex`; interpreted MATLAB has different performance characteristics |
| Test script run under `coder.runTest` without `assert` statements | Always include assertions — `coder.runTest` produces no output on success otherwise |
| Building MEX in every test method with identical input types | Build once in `TestClassSetup`; rebuild per test only when input type specs differ |
| Calling the MATLAB function manually in `matlabtest.coder.TestCase` tests | `verifyExecutionMatchesMATLAB` calls MATLAB internally — just `execute` then verify |
| Command-syntax `-d (outDir)` for output directory | Function-call syntax: `codegen('func', '-config', cfg, '-args', types, '-d', outDir)` |
| Adding `-report`, `-launchreport`, or `GenerateReport = true` | Don't generate code reports unless explicitly requested |
| `IntegrityChecks = false` (MEX) without first running with checks on | Run with checks enabled across all expected inputs first; only disable after confirming no bounds errors |
| `EnableDynamicMemoryAllocation = false` and `EnableVariableSizing = false` together | Keep `EnableVariableSizing = true` so variable-size arrays stack-allocate at the upper bound |
| Growing array in loop (`x = [x; row]`) | Preallocate full array before loop |
| Using `try`/`catch` in codegen path | Return status codes; use `coder.target('MATLAB')` for MATLAB-only error handling |
| Variable changes type between assignments | One variable = one type throughout scope |
| Function returns different types/sizes on different paths | Ensure consistent output type and size on all paths |
| Missing `%#codegen` pragma | Always include after function signature |
| `coder.extrinsic` expecting runtime behavior in lib/dll | Extrinsic calls produce no code in portable targets; combine with `coder.const` |
| Using `coder.ClassSignature` / `-class` without enabling the Tech Preview | Run `enableCodegenForEntryPointClasses` once per MATLAB session before class code generation |

## Conventions

- Follow MathWorks Coding Guidelines for any MATLAB code suggested or written: `lowerCamelCase` functions, `arguments` blocks, max 6 inputs / 4 outputs, `end` terminators.
- For floating-point comparisons between MEX and MATLAB, use tolerances (`AbsTol` / `RelTol`) rather than exact equality. Differences < 1e-10 relative are normal due to different math libraries.
- For variable-size arrays, specify upper bounds via `coder.typeof(example, [maxDims], [variableFlags])`.
- Use `coder.Constant` for entrypoint inputs whose value is known at compile time so codegen can resolve downstream array sizes statically.

----

Copyright 2026 The MathWorks, Inc.

----