C Function Block Configuration
When to Use
- Calling or wrapping C/C++ code or libraries in Simulink
- Creating, configuring, or using a C Function block
- Integrating custom code, legacy code, or external C/C++ into a model
- Integrating a C++ class into a Simulink model or test bench
- Configuring inputs, outputs, or parameters for a C++ algorithm in a block
When NOT to Use
- Building general Simulink models without C/C++ integration
- MATLAB Function blocks (Embedded MATLAB) — those use MATLAB syntax, not C/C++
- Code generation workflows (Embedded Coder, Simulink Coder) — this skill is for simulation-time configuration only
Rules
- Derive each symbol's Simulink type from the corresponding C/C++ function parameter/return type (e.g.
float → single, bool → boolean, char*/char[] → string (R2024b+)). However, when replacing an existing block (e.g. an S-Function), use the types already on that block first — for example, what looks like int32 from C may actually be fixdt(1,32,3) or another fixed-point type in the existing model.
- MANDATORY for C++ classes: When the user's code defines a C++ class, you MUST first attempt to declare a Persistent symbol of
Class: ClassName and call class methods directly in the code sections (e.g. obj.Method(args)). If the class has an init method (not a constructor), call it in StartCode. Only fall back to wrapper/handler functions or opaque pointer patterns if the class approach fails to compile.
- Prefer relative paths for custom code files (sources, headers, libraries, search directories). Use paths relative to the model file location (e.g.
'myFunctions.h', './src/myLib.cpp') rather than absolute paths. This ensures portability across machines and users.
Workflow Overview
- Add the C Function block — use
model_edit with type "C Function" and set CustomCodeSettingLocation (default: "BlockSettings")
- Configure custom code settings — point to headers/sources either on the block or model config (see
references/custom-code-config.md)
- Set code sections — configure
OutputCode, StartCode, etc. on the block
- Configure symbols via SymbolSpec — use
model_query_params to get the SymbolSpec, then evaluate_matlab_code for object operations
SymbolSpec API (Port & Symbol Specification)
The SymbolSpec object defines the block's inputs, outputs, persistent state, constants, and parameters.
Getting the object
Query with model_query_params, then operate via evaluate_matlab_code:
obj = get_param('myModel/MyCFunction', 'SymbolSpec');
Adding, getting, deleting symbols
symObj = obj.addSymbol('varName'); % adds with default: Input, double, size '1'
symObj = obj.getSymbol('varName'); % get one by name
allSyms = obj.Symbols; % get all symbols
obj.deleteSymbol('varName');
Note: addSymbol always creates with defaults (double, Input, size '1'). When re-adding a deleted symbol, explicitly set all non-default properties (Type, Scope, Size) — prior properties are not retained.
Symbol Properties
| Property |
Values |
Default |
Notes |
Name |
identifier string |
(from addSymbol) |
Variable name in code; for class types includes constructor args |
Scope |
'Input', 'Output', 'InputOutput', 'Persistent', 'Constant', 'Parameter' |
'Input' |
See Scope Details below |
Type |
'double', 'single', 'int8'...'uint64', 'Boolean', 'string', 'Bus: BusName', 'Enum: EnumName', 'Class: ClassName', 'AliasTypeName', or fixedpoint |
'double' |
|
Size |
dimension string |
'1' |
e.g. '1', '3', '[2,3]', 'size(u1)' |
Label |
port label / value |
same as Name |
For Constant: the literal value |
PortNumber |
uint32 |
auto-assigned |
Port ordering |
Scope Details
| Scope |
Description |
Port? |
Input |
Block input port |
Yes (inport) |
Output |
Block output port |
Yes (outport) |
InputOutput |
Read-write pass-through (always first in port numbering) |
Yes (both) |
Persistent |
State that persists across time steps (also used for class instances) |
No |
Constant |
Compile-time constant (scalar only) |
No |
Parameter |
Tunable parameter from workspace/mask |
No |
Setting Parameter values
After setting Scope to 'Parameter', set the value by configuring the block with the parameter name as the key.
C++ Class Types
Class instances are declared as Persistent scope symbols with Type = 'Class: ClassName'.
Constructor arguments are specified in the Name property:
obj = get_param('myModel/CFunction', 'SymbolSpec');
% Default constructor (no args)
sym = obj.addSymbol('myObj');
sym.Scope = 'Persistent';
sym.Type = 'Class: MyClass';
% Constructor with arguments (args must be Parameter or Constant scope symbols)
sym = obj.addSymbol('myObj(p)');
sym.Scope = 'Persistent';
sym.Type = 'Class: MyClass';
Rules for class types:
- Class must be defined in an external header (included via custom code settings) — NOT inside code sections
- Cannot create class instances as local variables in code sections — applies when
CustomCodeSettingLocation = 'ModelConfigurationParameters' (always parsed), or 'BlockSettings' with ParseBlockCode = 'on'
- Constructor arguments must be Parameter or Constant scoped symbols only
- Function calls in constructor arguments are not allowed
new operator is not allowed when block code is parsed
- Private/protected members cannot be accessed from code sections
- Class type does not support save/restore (SimSnapshot)
Access class methods in code sections: y = myObj.compute(u1);
Size Expressions
- Scalar:
'1'
- Vector:
'3' or '[3,1]'
- Matrix:
'[2,3]'
- Dynamic from input:
'size(u1)', 'size(u1,1)', 'size(u1) + 1'
Rules:
size() IS allowed in output dimensions (compute output size from inputs)
size() is NOT allowed in input dimensions
- Output size CANNOT be
'-1' (inherited) — must be explicit or use size() expression
- Input size CAN be
'-1' (inherited)
- Size must evaluate to integer values
- Nested
size(size(...)) is NOT supported
Restrictions
#include directives NOT allowed inside code sections (Start/Output/Terminate) — use custom code settings
- Start/Terminate code CANNOT access Input or Output scoped symbols
- Constant scope must be scalar
- Library functions (e.g.
isalnum) not supported inside code sections when ParseBlockCode = 'on' or CustomCodeSettingLocation = 'ModelConfigurationParameters' — use external calls via header. No restriction under default R2026a+ settings (BlockSettings + ParseBlockCode = 'off')
- When using a
Simulink.NumericType with DataScope = 'Exported' in symbols, or any Simulink.NumericType in code sections, its IsAlias property must be true
- When
CustomCodeSettingLocation = 'UpdateBuildInfo', GenerateCodeAsIs is forced 'on'
- Class definitions NOT allowed inside code sections — define in external header
- Variable-size signals are not supported
Full Example: Block-Level Custom Code with C++ Function
% 1. Add C Function block with block-level custom code
% Use model_edit: add_block type "C Function", set CustomCodeSettingLocation,
% SimCustomHeaderFile, SimCustomSourceFile, and OutputCode on the block.
% 2. Configure symbols
obj = get_param('mMyTest/C Function', 'SymbolSpec');
obj.addSymbol('u1');
obj.addSymbol('u2');
u2obj = obj.getSymbol('u2');
u2obj.Type = 'int32';
u2obj.Size = '3';
obj.addSymbol('y');
yobj = obj.getSymbol('y');
yobj.Scope = 'Output';
yobj.Size = 'size(u2)';
obj.addSymbol('state');
stateobj = obj.getSymbol('state');
stateobj.Scope = 'Persistent';
save_system('mMyTest');
close_system('mMyTest', 0);
See references/examples.md for additional patterns (model-level custom code, C++ class with constructor args).
See references/custom-code-config.md for detailed parameter tables and custom code location settings.
Copyright 2026 The MathWorks, Inc.
1---2name: simulink-use-c-function-block3description: Use when integrating legacy code, custom code, or C/C++ code into Simulink via C Function blocks. Configure Simulink C Function blocks programmatically using the SymbolSpec API. TRIGGER when the user: - Asks about calling or wrapping C/C++ code or libraries in Simulink - Wants to create, configure, or use a C Function block - Mentions integrating custom code, legacy code, or external C/C++ into a model - Asks to integrate a C++ class into a Simulink model or test bench - Mentions inputs/outputs/parameters for a C++ algorithm block4license: https://www.mathworks.com/content/dam/mathworks/license/pmrl/lic5---6
7# C Function Block Configuration
8
9## When to Use
10
11- Calling or wrapping C/C++ code or libraries in Simulink
12- Creating, configuring, or using a C Function block
13- Integrating custom code, legacy code, or external C/C++ into a model
14- Integrating a C++ class into a Simulink model or test bench
15- Configuring inputs, outputs, or parameters for a C++ algorithm in a block
16
17## When NOT to Use
18
19- Building general Simulink models without C/C++ integration
20- MATLAB Function blocks (Embedded MATLAB) — those use MATLAB syntax, not C/C++
21- Code generation workflows (Embedded Coder, Simulink Coder) — this skill is for simulation-time configuration only
22
23## Rules
24
25- Derive each symbol's Simulink type from the corresponding C/C++ function parameter/return type (e.g. `float` → `single`, `bool` → `boolean`, `char*`/`char[]` → `string` (R2024b+)). However, when replacing an existing block (e.g. an S-Function), use the types already on that block first — for example, what looks like `int32` from C may actually be `fixdt(1,32,3)` or another fixed-point type in the existing model.
26- **MANDATORY for C++ classes:** When the user's code defines a C++ class, you MUST first attempt to declare a Persistent symbol of `Class: ClassName` and call class methods directly in the code sections (e.g. `obj.Method(args)`). If the class has an init method (not a constructor), call it in `StartCode`. Only fall back to wrapper/handler functions or opaque pointer patterns if the class approach fails to compile.
27- **Prefer relative paths** for custom code files (sources, headers, libraries, search directories). Use paths relative to the model file location (e.g. `'myFunctions.h'`, `'./src/myLib.cpp'`) rather than absolute paths. This ensures portability across machines and users.
28
29## Workflow Overview
30
311. **Add the C Function block** — use `model_edit` with type `"C Function"` and set `CustomCodeSettingLocation` (default: `"BlockSettings"`)
322. **Configure custom code settings** — point to headers/sources either on the block or model config (see `references/custom-code-config.md`)
333. **Set code sections** — configure `OutputCode`, `StartCode`, etc. on the block
344. **Configure symbols via SymbolSpec** — use `model_query_params` to get the SymbolSpec, then `evaluate_matlab_code` for object operations
35
36## SymbolSpec API (Port & Symbol Specification)
37
38The SymbolSpec object defines the block's inputs, outputs, persistent state, constants, and parameters.
39
40### Getting the object
41
42Query with `model_query_params`, then operate via `evaluate_matlab_code`:
43
44```matlab
45obj = get_param('myModel/MyCFunction', 'SymbolSpec');
46```
47
48### Adding, getting, deleting symbols
49```matlab
50symObj = obj.addSymbol('varName'); % adds with default: Input, double, size '1'
51symObj = obj.getSymbol('varName'); % get one by name
52allSyms = obj.Symbols; % get all symbols
53obj.deleteSymbol('varName');
54```
55
56**Note:** `addSymbol` always creates with defaults (`double`, `Input`, size `'1'`). When re-adding a deleted symbol, explicitly set all non-default properties (Type, Scope, Size) — prior properties are not retained.
57
58### Symbol Properties
59
60| Property | Values | Default | Notes |
61|----------|--------|---------|-------|
62| `Name` | identifier string | (from addSymbol) | Variable name in code; for class types includes constructor args |
63| `Scope` | `'Input'`, `'Output'`, `'InputOutput'`, `'Persistent'`, `'Constant'`, `'Parameter'` | `'Input'` | See Scope Details below |
64| `Type` | `'double'`, `'single'`, `'int8'`...`'uint64'`, `'Boolean'`, `'string'`, `'Bus: BusName'`, `'Enum: EnumName'`, `'Class: ClassName'`, `'AliasTypeName'`, or fixedpoint | `'double'` | |
65| `Size` | dimension string | `'1'` | e.g. `'1'`, `'3'`, `'[2,3]'`, `'size(u1)'` |
66| `Label` | port label / value | same as Name | For Constant: the literal value |
67| `PortNumber` | uint32 | auto-assigned | Port ordering |
68
69### Scope Details
70
71| Scope | Description | Port? |
72|-------|-------------|-------|
73| `Input` | Block input port | Yes (inport) |
74| `Output` | Block output port | Yes (outport) |
75| `InputOutput` | Read-write pass-through (always first in port numbering) | Yes (both) |
76| `Persistent` | State that persists across time steps (also used for class instances) | No |
77| `Constant` | Compile-time constant (scalar only) | No |
78| `Parameter` | Tunable parameter from workspace/mask | No |
79
80### Setting Parameter values
81
82After setting Scope to `'Parameter'`, set the value by configuring the block with the parameter name as the key.
83
84## C++ Class Types
85
86Class instances are declared as **Persistent** scope symbols with `Type` = `'Class: ClassName'`.
87
88**Constructor arguments are specified in the `Name` property:**
89
90```matlab
91obj = get_param('myModel/CFunction', 'SymbolSpec');
92
93% Default constructor (no args)
94sym = obj.addSymbol('myObj');
95sym.Scope = 'Persistent';
96sym.Type = 'Class: MyClass';
97
98% Constructor with arguments (args must be Parameter or Constant scope symbols)
99sym = obj.addSymbol('myObj(p)');
100sym.Scope = 'Persistent';
101sym.Type = 'Class: MyClass';
102```
103
104**Rules for class types:**
105- Class must be defined in an external header (included via custom code settings) — NOT inside code sections
106- Cannot create class instances as local variables in code sections — applies when `CustomCodeSettingLocation` = `'ModelConfigurationParameters'` (always parsed), or `'BlockSettings'` with `ParseBlockCode` = `'on'`
107- Constructor arguments must be **Parameter** or **Constant** scoped symbols only
108- Function calls in constructor arguments are not allowed
109- `new` operator is not allowed when block code is parsed
110- Private/protected members cannot be accessed from code sections
111- Class type does not support save/restore (SimSnapshot)
112
113Access class methods in code sections: `y = myObj.compute(u1);`
114
115## Size Expressions
116
117- Scalar: `'1'`
118- Vector: `'3'` or `'[3,1]'`
119- Matrix: `'[2,3]'`
120- Dynamic from input: `'size(u1)'`, `'size(u1,1)'`, `'size(u1) + 1'`
121
122**Rules:**
123- `size()` IS allowed in **output** dimensions (compute output size from inputs)
124- `size()` is NOT allowed in **input** dimensions
125- Output size CANNOT be `'-1'` (inherited) — must be explicit or use `size()` expression
126- Input size CAN be `'-1'` (inherited)
127- Size must evaluate to integer values
128- Nested `size(size(...))` is NOT supported
129
130## Restrictions
131
132- `#include` directives NOT allowed inside code sections (Start/Output/Terminate) — use custom code settings
133- Start/Terminate code CANNOT access Input or Output scoped symbols
134- Constant scope must be scalar
135- Library functions (e.g. `isalnum`) not supported inside code sections when `ParseBlockCode` = `'on'` or `CustomCodeSettingLocation` = `'ModelConfigurationParameters'` — use external calls via header. No restriction under default R2026a+ settings (`BlockSettings` + `ParseBlockCode` = `'off'`)
136- When using a `Simulink.NumericType` with `DataScope` = `'Exported'` in symbols, or any `Simulink.NumericType` in code sections, its `IsAlias` property must be `true`
137- When `CustomCodeSettingLocation` = `'UpdateBuildInfo'`, `GenerateCodeAsIs` is forced `'on'`
138- Class definitions NOT allowed inside code sections — define in external header
139- Variable-size signals are not supported
140
141## Full Example: Block-Level Custom Code with C++ Function
142
143```matlab
144% 1. Add C Function block with block-level custom code
145% Use model_edit: add_block type "C Function", set CustomCodeSettingLocation,
146% SimCustomHeaderFile, SimCustomSourceFile, and OutputCode on the block.
147
148% 2. Configure symbols
149obj = get_param('mMyTest/C Function', 'SymbolSpec');
150obj.addSymbol('u1');
151obj.addSymbol('u2');
152u2obj = obj.getSymbol('u2');
153u2obj.Type = 'int32';
154u2obj.Size = '3';
155obj.addSymbol('y');
156yobj = obj.getSymbol('y');
157yobj.Scope = 'Output';
158yobj.Size = 'size(u2)';
159obj.addSymbol('state');
160stateobj = obj.getSymbol('state');
161stateobj.Scope = 'Persistent';
162save_system('mMyTest');
163close_system('mMyTest', 0);
164```
165
166See `references/examples.md` for additional patterns (model-level custom code, C++ class with constructor args).
167See `references/custom-code-config.md` for detailed parameter tables and custom code location settings.
168
169----
170
171Copyright 2026 The MathWorks, Inc.
172
173----