Main Content

coder.extrinsic

Declare a function as extrinsic and execute it in MATLAB

Description

example

coder.extrinsic(function) declares function as an extrinsic function. The code generator does not produce code for the body of the extrinsic function and instead uses the MATLAB® engine to execute the call. This functionality is available only when the MATLAB engine is available during execution. Examples of situations where the MATLAB engine is available include execution of MEX functions, Simulink® simulations, or function calls at the time of code generation (also known as compile time).

During standalone code generation, the code generator attempts to determine whether an extrinsic function only has a side effect (for example, by displaying a plot) or whether it affects the output of the function in which it is called (for example, by returning a value to an output variable). If there is no change to the output, the code generator proceeds with code generation, but excludes the extrinsic function from the generated code. Otherwise, the code generator produces a compilation error.

You cannot use coder.ceval on functions that you declare as extrinsic by using coder.extrinsic. Also, the coder.extrinsic directive is ignored outside of code generation.

See Use MATLAB Engine to Execute a Function Call in Generated Code.

Note

The code generator automatically treats many common MATLAB visualization functions, such as plot, disp, and figure, as extrinsic. You do not have to explicitly declare them as extrinsic functions by using coder.extrinsic.

coder.extrinsic(function1, ... ,functionN) declares function1 through functionN as extrinsic functions.

coder.extrinsic('-sync:on', function1, ... ,functionN) enables synchronization of global data between MATLAB execution and generated code execution or Simulink simulation before and after calls to the extrinsic functions function1 through functionN. If only a few extrinsic calls use or modify global data, turn off synchronization before and after all extrinsic function calls by setting the global synchronization mode to At MEX-function entry and exit. Use the '-sync:on' option to turn on synchronization for only the extrinsic calls that do modify global data.

If you use MATLAB Coder™ to generate a MEX function, the '-sync:on' option enables verification of consistency of constant global data between MATLAB and MEX functions after calls to the extrinsic functions.

See Generate Code for Global Data.

coder.extrinsic('-sync:off', function1, ... ,functionN) disables synchronization of global data between MATLAB execution and generated code execution before and after calls to the extrinsic functions function1 through functionN. If most extrinsic calls use or modify global data, but a few do not, use the '-sync:off' option to turn off synchronization for the extrinsic calls that do not modify global data.

If you use MATLAB Coder to generate a MEX function, the '-sync:off' option disables verification of consistency of constant global data between MATLAB and MEX functions after calls to the extrinsic functions.

See Generate Code for Global Data.

Examples

collapse all

The MATLAB function patch is not supported for code generation. This example shows how you can still use the functionality of patch in your generated MEX function by declaring patch as extrinsic your MATLAB function.

This MATLAB code declares patch as extrinsic in the local function create_plot. By declaring patch as extrinsic, you instruct the code generator not to produce code for patch. Instead, the code generator dispatches patch to MATLAB for execution.

The code generator automatically treats many common MATLAB visualization functions, such as the function axis this code uses, as extrinsic.

function c = pythagoras(a,b,color) %#codegen
% Calculate the hypotenuse of a right triangle
% and display the triangle as a patch object. 
c = sqrt(a^2 + b^2);
create_plot(a, b, color);
end

function create_plot(a, b, color)
%Declare patch as extrinsic
coder.extrinsic('patch'); 
x = [0;a;a];
y = [0;0;b];
patch(x,y,color);
axis('equal');
end

Note

This code calls patch without requesting any output arguments. When generating standalone code, the code generator ignores such calls.

Generate a MEX function for pythagoras. Also, generate the code generation report.

codegen pythagoras -args {1, 1, [.3 .3 .3]} -report

In the report, view the MATLAB code for create_plot.

The report highlights the patch and axis functions to indicate that they are treated as extrinsic functions.

Run the MEX function.

pythagoras_mex(3, 4, [1.0 0.0 0.0]);

MATLAB displays the plot of the right triangle as a red patch object.

Note

Instead of generating a MEX file by using the codegen command, you can also place the function pythagoras inside a MATLAB Function block in a Simulink model. When you simulate the model, the MATLAB Function block has similar behavior as pythagoras_mex.

The output that an extrinsic function returns at run time is an mxArray, also known as a MATLAB array. The only valid operations for an mxArray are storing it in a variable, passing it to another extrinsic function, or returning it to MATLAB. To perform any other opeation on an mxArray value, such as using it in an expression in your code, you must convert the mxArray to a known type at run time. To perform this action, assign the mxArray to a variable whose type is already defined by a prior assignment.

This example shows how to return an mxArray output from an extrinsic function directly to MATLAB. The next example shows how to convert the same mxArray output to a known type, and then use it in an expression inside your MATLAB function.

Define Entry-Point Function

Define a MATLAB function return_extrinsic_output that accepts source and target node indices for a directed graph as inputs and determines if the graph is acyclic by using the hascycles function. The hascycles function is not supported for code generation and is declared as extrinsic.

type return_extrinsic_output.m
function hasCycles = return_extrinsic_output(source,target)
coder.extrinsic('hascycles');
assert(numel(source) == numel(target))
G = digraph(source,target);
hasCycles = hascycles(G);
end

Generate and Call MEX Function

Generate MEX code for return_extrinsic_output. Specify the inputs to be unbounded vectors of type double.

codegen return_extrinsic_output -args {coder.typeof(0,[1 Inf]),coder.typeof(0,[1 Inf])} -report
Code generation successful: To view the report, open('codegen/mex/return_extrinsic_output/html/report.mldatx')

Call the generated MEX function return_extrinsic_output_mex with suitable inputs:

return_extrinsic_output([1 2 4 4],[2 3 3 1])
ans = logical
   0

To visually inspect if the directed graph has cycles, plot the directed graph in MATLAB.

plot(digraph([1 2 4 4],[2 3 3 1]))

Figure contains an axes object. The axes object contains an object of type graphplot.

The output that an extrinsic function returns is an mxArray, also known as a MATLAB array. The only valid operations for an mxArray are storing it in a variable, passing it to another extrinsic function, or returning it to MATLAB. To perform any other operation on an mxArray value, such as using it in an expression in your code, convert the mxArray to a known type at run time. To perform this action, assign the mxArray to a variable whose type is already defined by a prior assignment.

This example shows how to convert the mxArray output of an extrinsic function to a known type, and then use the output in an expression inside your MATLAB function.

Define Entry-Point Function

Define a MATLAB function use_extrinsic_output that accepts source and target node indices for a directed graph as inputs and determines if the graph is acyclic by using the hascycles function. The hascycles function is not supported for code generation and is declared as extrinsic. The entry-point function displays a message based on the output of the hascycles function.

type use_extrinsic_output
function use_extrinsic_output(source,target) %#codegen
assert(numel(source) == numel(target))
G = digraph(source,target);

coder.extrinsic('hascycles');
hasCycles = true;

hasCycles = hascycles(G);
if hasCycles == true
    disp('The graph has cycles')
else
    disp('The graph does not have cycles')
end
end

The local variable hasCycles is first preassigned the Boolean value true before the assignment hasCycles = hascycles(G) occurs. This preassignment enables the code generator to convert the mxArray that the extrinsic function hascycles returns to a Bsoolean before assigning it to the hasCycles variable. This conversion in turn enables you to compare hasCycles with the Boolean true in the condition of the if statement.

Generate and Call MEX Function

Generate MEX code for use_extrinsic_output. Specify the inputs to be unbounded vectors of type double.

codegen use_extrinsic_output -args {coder.typeof(0,[1 Inf]),coder.typeof(0,[1 Inf])} -report
Code generation successful: To view the report, open('codegen/mex/use_extrinsic_output/html/report.mldatx')

Call the generated MEX function use_extrinsic_output_mex with suitable inputs:

use_extrinsic_output_mex([1 2 4 4],[2 3 3 1])
The graph does not have cycles

To see if the directed graph has cycles, plot the graph in MATLAB.

plot(digraph([1 2 4 4],[2 3 3 1]))

Figure contains an axes object. The axes object contains an object of type graphplot.

This example shows how to call an extrinsic function at the time of code generation (also known as compile time) by using coder.const. Because the MATLAB engine is always available during the evaluation of the expression inside coder.const, you can use this coding pattern when generating either MEX or standalone code. Unlike the previous two examples that show run-time execution, you do not need to explicitly convert the output of the extrinsic function to a known type if its evaluation happens at compile time.

In this example, the entry-point function rotate_complex invokes another function xml2struct that uses the MATLAB API for XML processing. Because code generation does not support the MATLAB API for XML processing, the xml2struct function is declared as extrinsic in the body of the entry-point function. Also, the call to xml2struct inside the entry-point function returns a compile-time constant. So, this output is constant-folded by placing the function call inside the coder.const directive.

Inspect XML File Containing Parameters

The supporting file complex.xml contains the values of real and imaginary parts of a complex number.

type complex.xml
<params>
    <param name="real" value="3"/>
    <param name="imaginary" value="4"/>
</params>

Define xml2struct Function

The MATLAB function xml2struct reads an XML file that uses the format of complex.xml to store parameter names and values, stores this information as structure fields, and returns this structure.

type xml2struct.m
function s = xml2struct(file)
s = struct();
doc = xmlread(file);
els = doc.getElementsByTagName("params");
for i = 0:els.getLength-1
    it = els.item(i);
    ps = it.getElementsByTagName("param");
    for j = 0:ps.getLength-1
        param = ps.item(j);
        paramName = char(param.getAttribute("name"));
        paramValue = char(param.getAttribute("value"));
        paramValue = evalin("base", paramValue);
        s.(paramName) = paramValue;
    end
end

Define Entry-Point Function

Your MATLAB entry-point function rotate_complex first calls xml2struct to read the file complex.xml. It then rotates the complex number by an angle that is equal to the input argument theta in degrees and returns the resulting complex number.

type rotate_complex.m
function y = rotate_complex(theta) %#codegen
coder.extrinsic("xml2struct");
s = coder.const(xml2struct("complex.xml"));

comp = s.real + 1i * s.imaginary;
magnitude = abs(comp);
phase = angle(comp) + deg2rad(theta);
y = magnitude * cos(phase) + 1i * sin(phase);

end

The xml2struct function is declared as extrinsic and its output is constant-folded by placing the function inside the coder.const directive.

Generate and Inspect Static Library

Generate a static library for read_complex by using the codegen command. Specify the input type to be a scalar double.

codegen -config:lib rotate_complex -args {0} -report 
Code generation successful: To view the report, open('codegen/lib/rotate_complex/html/report.mldatx')

Inspect the generated C++ file rotate_complex.c. Observe that the output of the xml2struct function is hardcoded in the generated code.

type codegen/lib/rotate_complex/rotate_complex.c
/*
 * rotate_complex.c
 *
 * Code generation for function 'rotate_complex'
 *
 */

/* Include files */
#include "rotate_complex.h"
#include <math.h>

/* Function Definitions */
creal_T rotate_complex(double theta)
{
  creal_T y;
  double y_tmp;
  y_tmp = 0.017453292519943295 * theta + 0.92729521800161219;
  y.re = 5.0 * cos(y_tmp);
  y.im = sin(y_tmp);
  return y;
}

/* End of code generation (rotate_complex.c) */

Input Arguments

collapse all

Name of the MATLAB function that is declared as extrinsic.

Example: coder.extrinsic('patch')

Data Types: char

Limitations

  • Extrinsic function calls have some overhead that can affect performance. Input data that is passed in an extrinsic function call must be provided to MATLAB, which requires making a copy of the data. If the function has any output data, this data must be transferred back into the MEX function environment, which also requires a copy.

  • The code generator does not support the use of coder.extrinsic to call functions that are located in a private folder.

  • The code generator does not support the use of coder.extrinsic to call local functions.

Tips

  • The code generator automatically treats many common MATLAB visualization functions, such as plot, disp, and figure, as extrinsic. You do not have to explicitly declare them as extrinsic functions by using coder.extrinsic.

  • Use the coder.screener function to detect which functions you must declare as extrinsic. This function runs the Code Generation Readiness Tool that screens the MATLAB code for features and functions that are not supported for code generation.

Extended Capabilities

C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.

GPU Code Generation
Generate CUDA® code for NVIDIA® GPUs using GPU Coder™.

Version History

Introduced in R2011a