主要内容

Generate Code for a MATLAB Function That Expands a Vector in a Loop

This example shows how to generate C and C++ code for a MATLAB® function that uses bounded and unbounded variable-size arrays.

Create MATLAB Function and Sample Data

Create a MATLAB function, myuniquetol. This function identifies the elements of input vector A that are unique with respect to the specified tolerance tol. After sorting A, the function iterates through the elements of A. It adds element A(i) to B only if the absolute value of the difference between A(i) and the element most recently added to B is greater than tol. The function then returns B.

type myuniquetol.m
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

Generate a 10-element vector of noisy values and use myuniquetol to identify the unique elements of this vector given a tolerance of 0.05.

noisyData = 0.01*sin(1:10)+[1.01, 1.02, 1.03, 2.05, 2.10, 3.00, 3.01, 4.50, 5.00, 5.05];
cleanData = myuniquetol(noisyData,0.05)
cleanData = 1×5

    1.0184    2.0424    2.9972    4.5099    5.0041

Prepare MATLAB Code for Code Generation

Rename the myuniquetol function to myuniquetolCG. Add the %#codegen directive to myuniquetolCG to prompt the MATLAB Code Analyzer to identify warnings and errors specific to code generation. Examine this function in the MATLAB Editor. The Code Analyzer detects that variable B might change size in the for-loop and issues a warning. Because vector B expands in size when it adds values from vector A, you can ignore this warning.

type myuniquetolCG.m
function B = myuniquetolCG(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

Generate and Test MEX Function

It is important to generate and test a MEX function before you generate C/C++ code. Running the MEX function in MATLAB before generating C/C++ code enables you to detect and fix run-time errors. In addition, you can use the MEX function to verify that your generated code functions similarly to your original MATLAB code.

Use the codegen command to generate a MEX function from myuniquetolCG. Use the -report option to generate a report and use the -args option to specify these input argument types:

  • Define the first input argument as a variable-length row vector with a maximum length of 100 by using coder.typeof.

  • Define the second input argument as a fixed-size scalar by example.

codegen myuniquetolCG -args {coder.typeof(0,[1,100],[false,true]),0} -report
Code generation successful: View report

Open the report and examine the definitions in the Variables tab. B is an unbounded row vector and A is a variable-length vector with an upper bound length of 100.

Test the MEX function with the same input that you passed to the original MATLAB function and compare the results. The MEX function produces the same output.

cleanData_mex = myuniquetolCG_mex(noisyData,0.05)
cleanData_mex = 1×5

    1.0184    2.0424    2.9972    4.5099    5.0041

Generate C Code

Generate a static C library for myuniquetolCG and specify the same input arguments you used to generate the MEX function. 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 array is greater than or equal to the threshold or if the array is unbounded, codegen allocates memory dynamically on the heap.

codegen myuniquetolCG -config:lib -args {coder.typeof(0,[1,100],[false,true]),0} -report
Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because
Embedded Coder is not installed, this might cause some Embedded Coder features
to fail.


Code generation successful (with warnings): View report

Examine the function declaration in the file myuniquetolCG.h.

myfile = fullfile("codegen","lib","myuniquetolCG","myuniquetolCG.h");
coder.example.extractLines(myfile,"/* Function Declarations */",");",0,1)
extern void myuniquetolCG(const double A_data[], const int A_size[2],
                          double tol, emxArray_real_T *B);

The code generator computes the size of A and allocates this memory statically because the maximum size of A is less than the default dynamic memory allocation threshold of 64 kilobytes. The generated function declaration contains:

  • double A_data[],which is the definition of A.

  • const int A_size[2], which is the actual size of the input.

  • double tol, which is the definition of tol.

  • emxArray_real_T *B, which is the definition of B.

The code generator determines that B is variable size with unknown upper bounds, and represents B as a variable-size array type known as an emxArray. MATLAB Coder™ provides utility functions for creating and interacting with these types of arrays in the generated code. For more information, see Use Dynamically Allocated C Arrays in the Generated Function Interfaces.

Generate C++ Code

Generate a static C++ library for myuniquetolCG, and specify the same input arguments you used to generate the MEX function. Use the -lang option to specify C++ as the target language. To prevent the code generator overwriting the C code you generated previously, use the -d option to specify a different output folder.

codegen myuniquetolCG -config:lib -lang:c++ -d myuniquetolCG_cpp -args {coder.typeof(0,[1,100],[false,true]),0} -report
Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because
Embedded Coder is not installed, this might cause some Embedded Coder features
to fail.


Code generation successful (with warnings): View report

Examine the function declaration in the file myuniquetolCG.h.

myfile = fullfile("myuniquetolCG_cpp","myuniquetolCG.h");
coder.example.extractLines(myfile,"// Function Declarations",");",0,1)
extern void myuniquetolCG(const double A_data[], const int A_size[2],
                          double tol, coder::array<double, 2U> &B);

The generated C++ function declaration is similar to the C function declaration, except that the dynamically allocated array is a coder::array class template instead of an emxArray. To learn how to use the coder::array class template in your custom C++ code, see Use Dynamically Allocated C++ Arrays in Generated Function Interfaces.

Generate C Code Using Dynamic Memory Allocation for Fixed-Size Input Array

Dynamic memory allocation can reduce the speed of the generated code. However, for larger arrays, dynamic memory allocation can reduce storage requirements. If you specify A as a very large variable-size array, the code generator dynamically allocates memory for A on the heap. For more information about controlling dynamic memory allocation for variable-size arrays, see Control Dynamic Memory Allocation in Generated Code.

codegen myuniquetolCG -config:lib -args {coder.typeof(0,[1,10000],[false,true]),0} -report
Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because
Embedded Coder is not installed, this might cause some Embedded Coder features
to fail.


Code generation successful (with warnings): View report
myfile = fullfile("codegen","lib","myuniquetolCG","myuniquetolCG.h");
coder.example.extractLines(myfile,"/* Function Declarations */",");",0,1)
extern void myuniquetolCG(const emxArray_real_T *A, double tol,
                          emxArray_real_T *B);

Generate C Code for Bounded Output Vector

Because input A is variable size and has an upper bound of 100, the output vector B contains at most 100 elements. Use coder.varsize to set the upper-bound length of B to 100 elements.

type myuniquetolCG_bounded.m
function B = myuniquetolCG_bounded(A,tol) %#codegen
coder.varsize("B",[1,100],[false,true]);
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

Generate code for this function, and specify the same input types you used to generate the MEX function. Examine the function declaration. The code generator statically allocates the memory for B and stores the size of B in int B_size[2].

codegen myuniquetolCG_bounded -config:lib -args {coder.typeof(0,[1,100],[false,true]),0} -report
Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because
Embedded Coder is not installed, this might cause some Embedded Coder features
to fail.


Code generation successful (with warnings): View report
myfile = fullfile("codegen","lib","myuniquetolCG_bounded","myuniquetolCG_bounded.h");
coder.example.extractLines(myfile,"/* Function Declarations */",");",0,1)
extern void myuniquetolCG_bounded(const double A_data[], const int A_size[2],
                                  double tol, double B_data[], int B_size[2]);

See Also

| |

Topics