Main Content

Pass an Entry-Point Function Output as an Input

When you generate code for multiple entry-point functions, you must specify the input types for each function. Using coder.OutputType, you can pass the output type of one function as the input type to another function. For example, to use the type of the second output from a function foo1 as the input type to a function foo2, enter:

codegen foo1 -args {7, 42} foo2 -args {coder.OutputType('foo1',2)} 

You can also use coder.OutputType to facilitate the process of partitioning, componentizing, or extending your code base. For example, when your MATLAB® code uses or accepts a complicated, aggregate data type, consider creating a separate constructor function that creates that data type. Then, generate code for multiple entry-point functions, using coder.OutputType to pass the output type from the constructor to your other entry-point functions.

For more information on using multiple entry-point functions, see Generate Code for Multiple Entry-Point Functions.

Pass an Entry-Point Function Output as an Input to Another Entry-Point Function

The coder.OutputType function provides a way to chain together entry-point functions that use the same data types. Use coder.OutputType to:

  • Simplify the input type specification process. When an existing entry-point function creates or defines a data type, you can reuse that definition for the input to a different entry-point function.

  • Synchronize and align data between entry-point functions. When you use coder.OutputType to pass a data type, there is only a single source for the type definition, and that definition is used by both functions.

To understand these advantages, compare two cases where you generate code with and without using coder.OutputType.

Example: Reuse a Nested Structure Output Type as an Input Type

Suppose that you have a complicated data type that is important to your code base. You have multiple entry-point functions that rely on this data type for input, output, and internal computation. You require the interfaces between the generated function code to use the same type definition.

For the purposes of this example, suppose that the data type is a nested structure, with a variable-size array stored in the lowest-level property. You want to name this structure type squiggle in the generated code. In MATLAB, you write a constructing function for the data type called myConstuctor:

function [out] = myConstructor(a, b)
% create a variable-sized array with upper bounds of 100-by-100
coder.varsize('myStruct.f1.f2.f3.f4', [100 100], [1 1]);
% define the nested structure type
myStruct = struct('f1', struct('f2', struct('f3', struct('f4', zeros(a,b) ))));
% specify the name of the structure and one of its fields
coder.cstructname(myStruct.f1.f2.f3,'squiggle_f3');
coder.cstructname(myStruct,'squiggle');
out = myStruct;

You write a second function, useConstructor, that takes the squiggle type as input, performs addition, and pushes additional columns on to the end of the data.

function x = useConstructor(x, n)
xz = x.f1.f2.f3.f4;
b = zeros(size(xz,1),1);
for i = 1:n
    xz = [(xz + pi), b];
end
x.f1.f2.f3.f4 = xz;

To generate code for myConstructor and useConstructor and treat them as multiple entry-point functions, you must specify the input types for both functions. Specify the input types for myConstructor by using two integers. For useConstructor, specify the input type as the output type from myConstructor by using coder.OutputType:

v = coder.OutputType('myConstructor');
codegen myConstructor -args {5,1} useConstructor -args {v,3} -report -config:lib

In the generated code, the function interfaces are aligned. The two entry-point functions use the same type definition for squiggle. You can use the generated code for the constructor to create an input type for the generated code for useConstructor.

Example: Manually Define an Input Type Without Using coder.OutputType

If you do not use coder.OutputType to define the input type for useConstructor, you must specify the input type by using coder.typeof and coder.StructType class properties:

% MATLAB type definition for squiggle
myStruct = struct('f1', struct('f2', struct('f3', struct('f4', zeros(2) ))));
t = coder.typeof(myStruct);
t.Fields.f1.Fields.f2.Fields.f3.Fields.f4 = coder.typeof(zeros(2), [100 100], [1 1]);
t.Fields.f1.Fields.f2.Fields.f3.TypeName = 'squiggle_f3';
t.TypeName = 'squiggle';

To generate static library code, enter:

codegen myConstructor -args {5,1} useConstructor -args {t,3} -report -config:lib

As in the first example, the function interfaces are aligned. However, creating and maintaining the type definition for squiggle is labor-intensive. Changes that you make to the type definition must be replicated in two places: the myConstructor function and the current workspace variable t. These changes can fall out of synchronization, particularly when working with complicated type definitions. Use coder.OutputType to assist in your development process.

Use coder.OutputType to Facilitate Code Componentization

If your MATLAB code uses large, complicated, or aggregate type definitions, you can separate your code into different entry-point function components (such as a constructor and an operator) and use coder.OutputType to pass the type definition between them. The coder.OutputType function enables you to ensure a matching interface between the different entry-point functions.

Example: Create a Constructor and Use coder.OutputType to Pass the Output Type

Consider the function useSparse that performs an operation on a sparse matrix input.

function out = useSparse(in)
%#codegen
out = in*2;

If you generate code for useSparse, you must manually construct the appropriate input type in C/C++. To automate and simplify the type construction, write a constructor for the sparse matrix.

function A = makeSparse(i,j,v,m,n)
%#codegen
A = sparse(i,j,v,m,n);

To generate code, use coder.OutputType to pass the output from the constructor as the input to useSparse. Define your input argument as a 3-by-5 matrix.

t = coder.OutputType('makeSparse');
S = round(rand(3,5));
[m,n] = size(S);
[i,j,v] = find(S);
i = coder.typeof(i,[inf 1]); % allow number of nonzero entries to vary
codegen makeSparse -args {i,i,i,m,n} useSparse -args {t} -report

Using the generated C/C++ code, you can call makeSparse to generate the input to useSparse. The coder.OutputType function makes it easy to create and align the interface for separate entry-point functions that belong to a common code base.

See Also

| | | |

Related Topics