Main Content

coder.extrinsic

Declare 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, and function calls at the time of code generation (also known as compile time).

During the generation of standalone code, the code generator attempts to determine whether the extrinsic function affects the function in which it is called. If the extrinsic function does not affect the calling function (for example, the extrinsic function displays a plot), the code generator proceeds with code generation, but excludes the extrinsic function from the generated code. If the extrinsic function affects the calling function (for example, the extrinsic function returns a value to the calling function), the code generator produces a compilation error.

MATLAB ignores the coder.extrinsic directive outside of code generation.

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

Note

The run-time output of an extrinsic function 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, you must convert the mxArray to a known type by assigning the mxArray to a variable whose type is already defined by a prior assignment. See Working with mxArrays.

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

coder.extrinsic(syn, function1, ... ,functionN) controls synchronization of global data between your MATLAB code and the generated MEX file before and after the extrinsic function call. By default, the code generator synchronizes global variables before and after extrinsic function calls to maximize consistency between the MATLAB code and the MEX function. To learn how and when to change this default behavior, see Generate Code for Global Data.

Examples

collapse all

Define the local function convertStringToNumber, which displays the output of the MATLAB function str2num. Because str2num is not supported for code generation, you must declare this function as extrinsic in your MATLAB code. By declaring str2num as extrinsic, you instruct the code generator not to produce code for str2num. Instead, the code generator dispatches str2num to MATLAB for execution. convertStringToNumber displays the value returned by str2num using disp, which the code generator automatically treats as extrinsic.

type("convertStringToNumber.m")
function convertStringToNumber(c) %#codegen
    coder.extrinsic("str2num");
    disp(str2num(c));
end

Generate MEX code for convertStringToNumber. Specify the input to be an unbounded character vector.

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

In the file convertStringToNumber.c, which you can view from the code generation report, you can see that no C code is generated for the MATLAB functions disp and str2num. Instead, the generated code sends these functions to MATLAB for execution using the internal function emlrtCallMATLABR2012b.

Call the generated MEX code for convertStringToNumber using a character vector:

convertStringToNumber_mex('123')
   123
convertStringToNumber_mex('1,2,3')
     1     2     3
convertStringToNumber_mex(num2str(1:10))
     1     2     3     4     5     6     7     8     9    10

Define the local function returnStringToNumber, which returns the output of the MATLAB function str2num to MATLAB. Because str2num is not supported for code generation, you must declare this function as extrinsic in your MATLAB code. By declaring str2num as extrinsic, you instruct the code generator not to produce code for str2num. Instead, the code generator dispatches str2num to MATLAB for execution. The value that str2num 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. See Working with mxArrays.

type returnStringToNumber.m
function num = returnStringToNumber(c) %#codegen
    coder.extrinsic("str2num");
    num = str2num(c);
end

Generate MEX code for returnStringToNumber. Specify the input to be an unbounded character vector.

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

In the code generation report, you can see that num is an mxArray.

Call the generated MEX code for returnStringToNumber using a character vector:

a = returnStringToNumber_mex('123')
a = 123
b = returnStringToNumber_mex('1,2,3')
b = 1×3

     1     2     3

c = returnStringToNumber_mex(num2str(1:10))
c = 1×10

     1     2     3     4     5     6     7     8     9    10

Even though returnStringToNumber_mex returns an mxArray, MATLAB correctly interprets the output as a numeric vector.

Define the local function useStringToNumber, which displays different messages based on the output of the MATLAB function str2num. Because str2num is not supported for code generation, you must declare this function as extrinsic in your MATLAB code. By declaring str2num as extrinsic, you instruct the code generator not to produce code for str2num. Instead, the code generator dispatches str2num to MATLAB for execution. The value that str2num 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 operation on an mxArray value, such as using it in an expression in your code, you must convert the mxArray to a known type by assigning the mxArray to a variable whose type is already defined by a prior assignment. See Working with mxArrays.

To use the mxArray that str2num returns in useStringToNumber, initialize num as a double before the extrinsic function call. At compile time, the code generator automatically converts the mxArray returned by str2num to a double, which you can then use in subsequent expressions. If you do not set num to a known type before using it in an expression, code generation fails.

type useStringToNumber.m
function useStringToNumber(c) %#codegen
   coder.extrinsic("str2num");
   num = 0;                 % initialize num as a scalar double
   num = str2num(c(1));     % force str2num to return a scalar double
   if num == 1              % because num is a known type, it can be used in expressions
       disp('Starts from one');
   else
       disp('Does not start from one');
   end
end

Generate MEX code for useStringToNumber. Specify the input to be an unbounded character vector.

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

In the code generation report, you can see that the output of str2num is an mxArray and num is a 1 x 1 double.

Call the generated MEX code for useStringToNumber using a character vector:

useStringToNumber_mex('1,2,3')
Starts from one
useStringToNumber_mex('3,2,1')
Does not start from one

Define the local function useStringToNumberVarSize, which returns arrays of different sizes based on the output of the MATLAB function str2num. Because str2num is not supported for code generation, you must declare this function as extrinsic in your MATLAB code. By declaring str2num as extrinsic, you instruct the code generator not to produce code for str2num. Instead, the code generator dispatches str2num to MATLAB for execution. The value returned by str2num 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 operation on an mxArray value, such as using it in an expression in your code, you must convert the mxArray to a known type by assigning the mxArray to a variable whose type is already defined by a prior assignment. See Working with mxArrays.

Because the size of the mxArray output of str2num is variable at run time, first initialize num as a known type (an empty array of doubles) and then declare num as variable-sized using coder.varsize. If you do not set num to a known type before using it, code generation fails. If you do not declare num as variable-sized, MEX execution fails for all nonempty arrays. To learn more about handling variable-size data for code generation, see Code Generation for Variable-Size Arrays.

type useStringToNumberVarSize.m
function num = useStringToNumberVarSize(c) %#codegen
    coder.extrinsic("str2num");
    num = [];                   % initialize num as an empty array of doubles
    coder.varsize("num");       % declare num as variable-sized
    num = str2num(c);           % because num is known to be variable-sized, the generated code does not error when passed a non-empty vector
    if numel(num) > 5           % because num is a known type and not an mxArray, it can be used in expressions
        num = num(1:5);
    end
end

Generate MEX code for useStringToNumberVarSize. Specify the input to be an unbounded character vector.

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

In the code generation report, you can see that the output of str2num is an mxArray and that num is a variable-sized (:? x :?) array of doubles.

Call the generated MEX code for useStringToNumberVarSize using a character vector:

a = useStringToNumberVarSize_mex('1,2,3')
a = 1×3

     1     2     3

b = useStringToNumberVarSize_mex(num2str(1:10))
b = 1×5

     1     2     3     4     5

As expected, useStringToNumberVarSize_mex returns a 5-element numeric vector.

If you call an extrinsic function that returns a constant value, you can instruct the code generator to evaluate the extrinsic function at compile time using coder.const. The code generator will then use this constant in the generated code. You can use this coding pattern to generate standalone code that uses the output of extrinsic functions.

Define the entry-point function rotate_complex, which rotates the complex number in the file complex.xml by the input argument theta. The function rotate_complex invokes another local function, xml2struct, which uses the MATLAB API for XML processing to convert the XML-formatted number in the file complex.xml to a structure. Because code generation does not support the MATLAB API for XML processing, you must declare the xml2struct function as extrinsic in the body of the function rotate_complex. By declaring xml2struct as extrinsic, you instruct the code generator not to produce code for xml2struct. Instead, the code generator dispatches xml2struct to MATLAB for execution. However, because complex.xml does not change between code generation time and run time, you can instruct the code generator to treat the output of the extrinsic function xml2struct as a run-time constant using coder.const. Because the extrinsic function is constant-folded at code generation time, you do not need to explicitly convert the output of xml2struct to a known type.

Inspect the supporting file complex.xml, which contains the real and imaginary parts of a complex number.

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

Define the function xml2struct, which reads the passed XML file using the MATLAB API for XML processing, stores the XML parameter names and values as structure fields, and returns the structure.

type xml2struct.m
function s = xml2struct(file)
s = struct();
import matlab.io.xml.dom.*
doc = parseFile(Parser,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 the MATLAB entry-point function rotate_complex, which converts complex.xml to a structure using xml2struct. The function rotate_complex then rotates the complex number by an angle that is equal to the input argument theta in degrees and returns the resulting complex number. In this function, you declare the xml2struct function as extrinsic using the coder.extrinsic directive and constant-fold its output using the coder.const directive.

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

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

codegen -config:lib rotate_complex -args {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): 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
/*
 * File: rotate_complex.c
 *
 * MATLAB Coder version            : 23.2
 * C/C++ source code generated on  : 19-Aug-2023 11:06:49
 */

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

/* Function Definitions */
/*
 * Arguments    : double theta
 * Return Type  : creal_T
 */
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;
}

/*
 * File trailer for rotate_complex.c
 *
 * [EOF]
 */

Input Arguments

collapse all

MATLAB function to be called extrinsically, specified as a character vector.

Example: coder.extrinsic('patch')

Data Types: char

Global variable synchronization, specified as '-sync:on' or '-sync:off'. By default, the code generator synchronizes global variables before and after each extrinsic function call. To learn how and when to change this default behavior, see Generate Code for Global Data.

Example: coder.extrinsic('-sync:off','cellfun')

Limitations

  • You cannot use coder.ceval on functions that you declare as extrinsic by using coder.extrinsic.

  • Extrinsic function calls can affect performance, because the code generator copies the data that you pass to an extrinsic function and sends the data to MATLAB for execution. Conversely, MATLAB copies any output data for transfer back into the MEX function environment.

  • 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.

  • Code generation does not support values passed to or returned from extrinsic functions that are or contain:

    • Handle classes

    • Function handles

    • Opaque values (See coder.opaque.)

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 these functions as extrinsic 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, which screens your MATLAB code for features and functions that are not supported for code generation. See Check Code by Using the Code Generation Readiness Tool.

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