Variable-size data is data whose size might change at run time. You can use MATLAB® Coder™ to generate C/C++ code from MATLAB code that uses variable-size data. MATLAB supports bounded and unbounded variable-size data for code generation. Bounded variable-size data has fixed upper bounds. This data can be allocated statically on the stack or dynamically on the heap. Unbounded variable-size data does not have fixed upper bounds. This data must be allocated on the heap. By default, for MEX and C/C++ code generation, support for variable-size data is enabled and dynamic memory allocation is enabled for variable-size arrays whose size is greater than or equal to a configurable threshold.
By default, for MEX and C/C++ code generation, support for variable-size data is enabled. You modify variable sizing settings from the project settings dialog box, the command line, or using dialog boxes.
To open the Generate dialog box, on the Generate Code page, click the Generate arrow .
Click More Settings.
On the Memory tab, select or clear Enable variable-sizing.
Create a configuration object for code generation. For example, for a library:
cfg = coder.config('lib');
Set the EnableVariableSizing
option:
cfg.EnableVariableSizing = false;
Using the -config
option, pass the configuration object
to codegen
:
codegen -config cfg foo
By default, dynamic memory allocation is enabled for variable-size arrays whose size is greater than or equal to a configurable threshold. If you disable support for variable-size data (see Disable Support for Variable-Size Data), you also disable dynamic memory allocation. You can modify dynamic memory allocation settings from the project settings dialog box or the command line.
To open the Generate dialog box, on the Generate Code page, click the Generate arrow .
Click More Settings.
On the Memory tab, set Dynamic memory allocation to one of the following options:
Setting | Action |
---|---|
Never | Dynamic memory allocation is disabled. Variable-size data is allocated statically on the stack. |
For all
variable-sized arrays | Dynamic memory allocation is enabled for variable-size arrays. Variable-size data is allocated dynamically on the heap. |
For arrays with max size at or above
threshold | Dynamic memory allocation is enabled for variable-size arrays whose size is greater than or equal to the Dynamic memory allocation threshold. Variable-size arrays whose size is less than this threshold are allocated on the stack. |
Optionally, if you set Dynamic memory allocation to
For arrays with maximum size at or above
threshold
, configure Dynamic memory allocation
threshold to fine-tune memory allocation.
Create a configuration object for code generation. For example, for a MEX function:
mexcfg = coder.config('mex');
Set the DynamicMemoryAllocation
option:
Setting | Action |
---|---|
mexcfg.DynamicMemoryAllocation='Off'; | Dynamic memory allocation is disabled. Variable-size data is allocated statically on the stack. |
mexcfg.DynamicMemoryAllocation='AllVariableSizeArrays'; | Dynamic memory allocation is enabled for variable-size arrays. Variable-size data is allocated dynamically on the heap. |
mexcfg.DynamicMemoryAllocation='Threshold'; | Dynamic memory allocation is enabled for variable-size
arrays whose size (in bytes) is greater than or equal to the
value specified using the
DynamicMemoryAllocationThreshold
parameter. Variable-size arrays whose size is less than this
threshold are allocated on the stack. |
Optionally, if you set DynamicMemoryAllocation
to
'Threshold'
, configure
DynamicMemoryAllocationThreshold
to fine tune memory
allocation.
Using the -config
option, pass the configuration object
to
codegen
:
codegen -config mexcfg foo
Here is a basic workflow that first generates MEX code for verifying the generated code and then generates standalone code after you are satisfied with the result of the prototype.
To work through these steps with a simple example, see Generate Code for a MATLAB Function That Expands a Vector in a Loop
In the MATLAB Editor, add the compilation directive
%#codegen
at the top of your function.
This directive:
Indicates that you intend to generate code for the MATLAB algorithm
Turns on checking in the MATLAB Code Analyzer to detect potential errors during code generation
Address issues detected by the Code Analyzer.
In some cases, the MATLAB Code Analyzer warns you when your code assigns data a fixed size but later grows the data, such as by assignment or concatenation in a loop. If that data is supposed to vary in size at run time, you can ignore these warnings.
Generate a MEX function using codegen
to verify the generated
code. Use the following command-line options:
-args {coder.typeof...}
if you have variable-size
inputs
-report
to generate a code generation report
For example:
codegen -report foo -args {coder.typeof(0,[2 4],1)}
coder.typeof
to specify one variable-size input
for function foo
. The first argument, 0
,
indicates the input data type (double
) and complexity
(real
). The second argument, [2 4]
,
indicates the size, a matrix with two dimensions. The third argument,
1
, indicates that the input is variable sized. The upper
bound is 2 for the first dimension and 4 for the second dimension.During compilation, codegen
detects variables and
structure fields that change size after you define them, and reports these
occurrences as errors. In addition, codegen
performs a
run-time check to generate errors when data exceeds upper bounds.
Fix size mismatch errors:
Cause | How To Fix | For More Information |
---|---|---|
You try to change the size of data after its size has been locked. | Declare the data to be variable sized. | See Diagnosing and Fixing Size Mismatch Errors. |
Fix upper bounds errors
Cause | How To Fix | For More Information |
---|---|---|
MATLAB cannot determine or compute the upper bound | Specify an upper bound. | SeeSpecify Upper Bounds for Variable-Size Arrays and Diagnosing and Fixing Size Mismatch Errors. |
MATLAB attempts to compute an upper bound for unbounded variable-size data. | If the data is unbounded, enable dynamic memory allocation. | See Control Dynamic Memory Allocation. |
Generate C/C++ code using the codegen
function.
This example uses the function myuniquetol
. This function
returns in vector B
a version of input vector
A
, where the elements are unique to within tolerance
tol
of each other. In vector B
,
abs
(B
(i
) -
B
(j
)) > tol
for all
i
and j
. Initially, assume input vector
A
can store up to 100 elements.
function B = myuniquetol(A, tol) A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Add the %#codegen
compilation directive at the top of the
function:
function B = myuniquetol(A, tol) %#codegen A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
The Code Analyzer detects that variable B
might change size in
the for-
loop. It issues this
warning:
The variable 'B' appears to change size on every loop iteration. Consider preallocating for speed.
In this function, you expect vector B
to expand in size because
it adds values from vector A
. Therefore, you can ignore this
warning.
It is a best practice to generate MEX code before you generate C/C++ code. Generating MEX code can identify code generation issues that are harder to detect at run time.
Generate a MEX function for
myuniquetol
:
codegen -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
What do these command-line options mean?
Code generation is successful.
codegen
does not detect issues. In the current folder,
codegen
generates a MEX function for
myuniquetol
and provides a link to the code generation
report.
Click the View report link.
In the code generation report, select the Variables tab.
The size of A
is 1x:100
because you
specified that A
is variable size with an upper bound of
100
. The size of variable B
is
1x:?
, indicating that it is variable size with
no upper bounds.
Generate C code for variable-size inputs. By default, codegen
allocates memory statically for data whose size is less than the dynamic memory
allocation threshold of 64 kilobytes. If the size of the data is greater than or
equal to the threshold or is unbounded, codegen
allocates memory
dynamically on the heap.
Create a configuration option for C library generation:
cfg=coder.config('lib');
Issue this command:
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
codegen
generates a static library in the default
location, codegen\lib\myuniquetol
and provides a link to
the code generation report.
Click the View report link.
In the list of generated files, click
myuniquetol.h
.
The function declaration is:
extern void myuniquetol(const double A_data[], const int A_size[2], double tol, emxArray_real_T *B);
codegen
computes the size of A
and,
because its maximum size is less than the default dynamic memory allocation
threshold of 64k bytes, allocates this memory statically. The generated code
contains:
double A_data[]
: the definition of
A
.
int A_size[2]
: the actual size of the
input.
The code generator determines that B
is variable size
with unknown upper bounds. It represents B
as
emxArray_real_T
. MATLAB provides utility functions for creating and interacting with
emxArrays
in your generated code. For more
information, see C Code Interface for Arrays.
You specified that the input A
is variable size with an upper
bound of 100
. Therefore, you know that the output
B
cannot be larger than 100
elements.
Use coder.varsize
to indicate that
B
is variable size with an upper bound of
100
.
function B = myuniquetol(A, tol) %#codegen A = sort(A); coder.varsize('B', [1 100], [0 1]); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Generate code.
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
The function declaration is:
extern void myuniquetol(const double A_data[], const int A_size[2], double tol, double B_data[], int B_size[2]);
The code generator statically allocates the memory for B
.
It stores the size of B
in int
B_size[2]
.
In this step, you reduce the dynamic memory allocation threshold and generate code
for an input that exceeds this threshold. This step specifies that the second
dimension of A
has an upper bound of
10000
.
Change the upper bound of B
to match the upper bound of
A
.
function B = myuniquetol(A, tol) %#codegen A = sort(A); coder.varsize('B', [1 10000], [0 1]); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Set the dynamic memory allocation threshold to 4 kilobytes and generate code
where the size of input A
exceeds this
threshold.
cfg.DynamicMemoryAllocationThreshold=4096; codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 10000],1),coder.typeof(0)}
View the generated code in the report. Because the maximum size of
A
and B
now exceed the dynamic memory
allocation threshold, codegen
allocates
A
and B
dynamically on the heap. In
the generated code, A
and B
have type
emxArray_real_T
.
extern void myuniquetol(const emxArray_real_T *A, double tol, emxArray_real_T *B);