Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

coder.extrinsic

将函数声明为外部函数,并在 MATLAB 中执行它

说明

示例

coder.extrinsic(function)function 声明为外部函数。代码生成器不为外部函数体生成代码,而是使用 MATLAB® 引擎来执行调用。在执行期间,仅当 MATLAB 引擎可用时,此功能才可用。MATLAB 引擎可用的情形示例包括 MEX 函数的执行、Simulink® 仿真和代码生成时的函数调用(也称为编译时)。

在生成独立代码的过程中,代码生成器会尝试确定外部函数是否影响调用时所在的函数。如果外部函数不影响主调函数(例如,外部函数显示绘图),代码生成器会继续生成代码,但从生成的代码中排除外部函数。如果外部函数影响主调函数(例如,外部函数向主调函数返回值),代码生成器将产生编译错误。

在代码生成期间外,MATLAB 会忽略 coder.extrinsic 指令。

请参阅使用 MATLAB 引擎在 MATLAB Function 模块中执行函数调用

注意

外部函数的运行时输出是 mxArray,也称为 MATLAB 数组。对 mxArray 有效的操作只有下列几个:将其存储在变量中,将其传递给另一个外部函数,或将其返回到 MATLAB。要对 mxArray 值执行任何其他操作,例如在代码的表达式中使用它,您必须将 mxArray 转换为已知类型,方法是将 mxArray 赋给一个变量,该变量的类型已由之前的赋值定义。请参阅使用 mxArray (MATLAB Coder)

coder.extrinsic(function1,...,functionN) 通过 functionNfunction1 声明为外部函数。

coder.extrinsic(syn, function1, ... ,functionN) 用于控制外部函数调用前后您的 MATLAB 代码与生成的 MEX 文件之间的全局数据同步。默认情况下,代码生成器在外部函数调用前后同步全局变量,以最大程度地实现 MATLAB 代码和 MEX 函数之间的一致性。要了解如何以及何时更改此默认行为,请参阅Generate Code for Global Data (MATLAB Coder)

示例

全部折叠

定义局部函数 convertStringToNumber,该函数显示 MATLAB 函数 str2num 的输出。由于 str2num 不支持代码生成,因此您必须在 MATLAB 代码中将此函数声明为外部函数。通过将 str2num 声明为外部函数,您指示代码生成器不要为 str2num 生成代码。在这种情况下,代码生成器会将 str2num 调度给 MATLAB 来执行。convertStringToNumber 显示 str2num 使用 disp 返回的值,代码生成器会自动将该值视为外部值。

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

生成 convertStringToNumber 的 MEX 代码。将输入指定为无界字符向量。

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

在可从代码生成报告中查看的文件 convertStringToNumber.c 中,您可以看到没有为 MATLAB 函数 dispstr2num 生成 C 代码。在这种情况下,生成的代码使用内部函数 emlrtCallMATLABR2012b 将这些函数发送给 MATLAB 来执行。

使用字符向量调用为 convertStringToNumber 生成的 MEX 代码:

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

定义局部函数 returnStringToNumber,该函数将 MATLAB 函数 str2num 的输出返回到 MATLAB。由于 str2num 不支持代码生成,因此您必须在 MATLAB 代码中将此函数声明为外部函数。通过将 str2num 声明为外部函数,您指示代码生成器不要为 str2num 生成代码。在这种情况下,代码生成器会将 str2num 调度给 MATLAB 来执行。str2num 在运行时返回的值是 mxArray,也称为 MATLAB 数组。对 mxArray 有效的操作只有下列几个:将其存储在变量中,将其传递给另一个外部函数,或将其返回到 MATLAB。请参阅使用 mxArray (MATLAB Coder)

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

生成 returnStringToNumber 的 MEX 代码。将输入指定为无界字符向量。

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

在代码生成报告中,您可以看到 nummxArray

使用字符向量调用为 returnStringToNumber 生成的 MEX 代码:

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

即使 returnStringToNumber_mex 返回 mxArray,MATLAB 也能正确地将输出解释为数值向量。

定义局部函数 useStringToNumber,该函数根据 MATLAB 函数 str2num 的输出显示不同消息。由于 str2num 不支持代码生成,因此您必须在 MATLAB 代码中将此函数声明为外部函数。通过将 str2num 声明为外部函数,您指示代码生成器不要为 str2num 生成代码。在这种情况下,代码生成器会将 str2num 调度给 MATLAB 来执行。str2num 在运行时返回的值是 mxArray,也称为 MATLAB 数组。

mxArray 有效的操作只有下列几个:将其存储在变量中,将其传递给另一个外部函数,或将其返回到 MATLAB。要对 mxArray 值执行任何其他操作,例如在代码的表达式中使用它,您必须将 mxArray 转换为已知类型,方法是将 mxArray 赋给一个变量,该变量的类型已由之前的赋值定义。请参阅使用 mxArray (MATLAB Coder)

要使用 str2numuseStringToNumber 中返回的 mxArray,请在外部函数调用之前将 num 初始化为 double。在编译时,代码生成器会自动将 str2num 返回的 mxArray 转换为 double,您随后可在后续表达式中使用它。如果在表达式中使用 num 之前没有将其设置为已知类型,代码生成将失败。

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

生成 useStringToNumber 的 MEX 代码。将输入指定为无界 character 向量。

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

在代码生成报告中,您可以看到 str2num 的输出是 mxArray,而 num1 x 1 double

使用字符向量调用为 useStringToNumber 生成的 MEX 代码:

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

定义局部函数 useStringToNumberVarSize,该函数根据 MATLAB 函数 str2num 的输出返回不同大小的数组。由于 str2num 不支持代码生成,因此您必须在 MATLAB 代码中将此函数声明为外部函数。通过将 str2num 声明为外部函数,您指示代码生成器不要为 str2num 生成代码。在这种情况下,代码生成器会将 str2num 调度给 MATLAB 来执行。str2num 在运行时返回的值是 mxArray,也称为 MATLAB 数组。

mxArray 有效的操作只有下列几个:将其存储在变量中,将其传递给另一个外部函数,或将其返回到 MATLAB。要对 mxArray 值执行任何其他操作,例如在代码的表达式中使用它,您必须将 mxArray 转换为已知类型,方法是将 mxArray 赋给一个变量,该变量的类型已由之前的赋值定义。请参阅使用 mxArray (MATLAB Coder)

由于 str2nummxArray 输出的大小在运行时是可变的,因此,请先将 num 初始化为已知类型(空的 doubles 数组),然后使用 coder.varsize (MATLAB Coder)num 声明为可变大小。如果在使用 num 之前没有将其设置为已知类型,代码生成将失败。如果未将 num 声明为可变大小,则对于所有非空数组,MEX 执行都将失败。要了解有关如何处理代码生成中的可变大小数据的更多信息,请参阅可变大小数组的代码生成 (MATLAB Coder)

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

生成 useStringToNumberVarSize 的 MEX 代码。将输入指定为无界字符向量。

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

在代码生成报告中,您可以看到 str2num 的输出是 mxArray,而 num 是由 doubles 组成的可变大小数组 (:? x :?)

使用字符向量调用为 useStringToNumberVarSize 生成的 MEX 代码:

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

useStringToNumberVarSize_mex 按预期返回一个包含 5 个元素的数值向量。

如果您调用返回常量值的外部函数,则可以指示代码生成器在编译时使用 coder.const 计算外部函数。代码生成器随后将在生成的代码中使用此常量。您可以使用此编码模式来生成使用外部函数输出的独立代码。

定义入口函数 rotate_complex,,该函数通过输入参数 theta 旋转文件 complex.xml 中的复数。函数 rotate_complex 调用另一个局部函数 xml2struct,,后者使用用于 XML 处理的 MATLAB API,将文件 complex.xml 中的 XML 格式数字转换为结构体。由于代码生成不支持用于 XML 处理的 MATLAB API,您必须在函数 rotate_complex 的主体中将 xml2struct 函数声明为外部函数。通过将 xml2struct 声明为外部函数,您可以指示代码生成器不为 xml2struct 生成代码。在这种情况下,代码生成器会将 xml2struct 调度给 MATLAB 来执行。但是,由于 complex.xml 在代码生成时间和运行时间之间不会更改,因此,您可以使用 coder.const 指示代码生成器将外部函数 xml2struct 的输出视为运行时常量。由于外部函数在代码生成时间是常量折叠的,因此,您不需要将 xml2struct 的输出显式转换为已知类型。

检查支持文件 complex.xml,该文件中包含复数的实部和虚部。

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

定义函数 xml2struct,该函数使用用于 XML 处理的 MATLAB API 读取传递的 XML 文件,将 XML 参数名称和值存储为结构体字段,并返回结构体。

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

定义 MATLAB 入口函数 rotate_complex,,该函数使用 xml2structcomplex.xml 转换为结构体。然后,函数 rotate_complex 将复数旋转一定角度(该角度等于输入参数 theta 的度数),并返回得到的复数。在此函数中,您可以使用 coder.extrinsic 指令将 xml2struct 函数声明为外部函数,并使用 coder.const 指令对其输出进行常量折叠。

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

使用 codegen (MATLAB Coder) 命令为 rotate_complex 生成静态库。将输入类型指定为 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')

检查生成的 C++ 文件 rotate_complex.c。注意 xml2struct 函数的输出硬编码在生成的代码中。

type codegen/lib/rotate_complex/rotate_complex.c
/*
 * File: rotate_complex.c
 *
 * MATLAB Coder version            : 23.2
 * C/C++ source code generated on  : 14-Aug-2023 19:19:45
 */

/* 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]
 */

输入参数

全部折叠

要从外部调用的 MATLAB 函数,指定为字符向量。

示例: coder.extrinsic('patch')

数据类型: char

全局变量同步,指定为 '-sync:on''-sync:off'。默认情况下,代码生成器在每次外部函数调用前后同步全局变量。要了解如何以及何时更改此默认行为,请参阅Generate Code for Global Data (MATLAB Coder)

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

限制

  • 对于您使用 coder.ceval (MATLAB Coder) 声明为外部函数的函数,不能使用 coder.extrinsic

  • 外部函数调用会影响性能,因为代码生成器会复制您传递给外部函数的数据,并将数据发送给 MATLAB 来执行。相反,MATLAB 会复制任何输出数据,以便传输回 MEX 函数环境中。

  • 代码生成器不支持使用 coder.extrinsic 来调用位于私有文件夹中的函数。

  • 代码生成器不支持使用 coder.extrinsic 来调用局部函数。

  • 如果传递给外部函数的值或从外部函数返回的值是以下项或包含以下项,则代码生成不支持这些值:

提示

  • 代码生成器自动将许多常见的 MATLAB 可视化函数(例如 plotdispfigure)视为外部函数。您不必使用 coder.extrinsic 将这些函数显式声明为外部函数。

  • 使用 coder.screener (MATLAB Coder) 函数可以检测哪些函数必须声明为外部函数。此函数运行代码生成就绪工具,它会筛查 MATLAB 代码中是否存在代码生成不支持的功能和函数。请参阅Check Code Using the Code Generation Readiness Tool

扩展功能

C/C++ 代码生成
使用 MATLAB® Coder™ 生成 C 代码和 C++ 代码。

GPU 代码生成
使用 GPU Coder™ 为 NVIDIA® GPU 生成 CUDA® 代码。

版本历史记录

在 R2011a 中推出