本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

用于代码生成的 MATLAB 类定义

要为 MATLAB® 类生成高效的独立代码,必须按照与在 MATLAB 环境中运行代码时不同的方式来使用类。

不同之处更多信息
受限的语言功能集。语言限制
受限的代码生成功能集。与类不兼容的代码生成功能
类属性的定义。为代码生成定义类属性
句柄类的使用。

Generate Code for MATLAB Handle Classes and System Objects

Code Generation for Handle Class Destructors

Handle Object Limitations for Code Generation

调用基类构造函数。基类构造函数的调用
代码生成不支持包含 MATLAB 句柄对象的全局变量。不适用
不支持从内置 MATLAB 类继承。不支持从内置 MATLAB 类继承

语言限制

虽然为类的常用功能(例如属性和方法)提供了代码生成支持,但仍有一些高级功能不受支持,例如:

  • 事件

  • 侦听程序

  • 对象数组

  • 递归数据结构体

    • 链表

  • 构造函数中的嵌套函数

  • 可重载运算符 subsrefsubsassignsubsindex

    在 MATLAB 中,类可以定义自己的 subsrefsubsassignsubsindex 方法版本。代码生成不支持拥有这些自定义方法的类。

  • empty 方法

    在 MATLAB 中,类具有内置的静态方法 empty,此方法将创建该类的空数组。代码生成不支持此方法。

  • 以下 MATLAB 句柄类方法:

    • addlistener

    • eq

    • findobj

    • findpro

  • AbortSet 属性特性

与类不兼容的代码生成功能

  • 可以为使用类的入口点 MATLAB 函数生成代码,但不能直接为 MATLAB 类生成代码。

    例如,如果 ClassNameA 是一个类定义,则不能通过执行以下命令来生成代码:

    codegen ClassNameA

  • 句柄类对象不能作为入口函数的输入或输出。

  • 值类对象可以作为入口函数的输入或输出。但是,如果值类对象包含句柄类对象,则值类对象不能作为入口函数的输入或输出。句柄类对象不能作为入口函数的输入或输出。

  • 代码生成不支持作为句柄类的全局变量。

  • 代码生成不支持将值类对象指定给不可调属性。例如,如果 prop 是不可调属性,而 v 是基于值类的对象,则 obj.prop=v; 无效。

  • 不能使用 coder.extrinsic 将类或方法声明为外部类或方法。

  • 不能将 MATLAB 类传递给 coder.ceval 函数。可以将类属性传递给 coder.ceval

  • 如果某属性具有 get 方法、set 方法或验证程序,或者是具有某些特性的 System object™ 属性,则您不能通过引用外部函数传递该属性。请参阅Passing By Reference Not Supported for Some Properties

  • 如果对象具有重复的属性名称,并且代码生成器尝试对该对象进行常量折叠,则代码生成可能会失败。当某对象与 coder.Constantcoder.const 结合使用时,或者当该对象作为常量折叠的外部函数的输入或输出时,代码生成器会对该对象进行常量折叠。

    在下列情况下,子类的对象中会出现重复的属性名称:

    • 子类具有与超类的某个属性名称相同的属性。

    • 子类派生于某一属性使用相同名称的多个超类。

    有关 MATLAB 何时允许重复的属性名称的信息,请参阅Subclassing Multiple Classes

为代码生成定义类属性

要进行代码生成,必须按照与在 MATLAB 环境中运行代码时不同的方式来定义类属性:

  • MEX 函数报告属性验证产生的错误。独立的 C/C++ 代码仅在启用运行时错误报告时才报告这些错误。请参阅Run-Time Error Detection and Reporting in Standalone C/C++ Code。在生成独立的 C/C++ 代码之前,最好通过在整个输入值范围内运行 MEX 函数来测试属性验证。

  • 定义属性之后,不要为其指定不兼容的类型。在使用属性之前,需对其进行必要的配置。

    定义类属性以进行代码生成时,需要考虑的因素与定义变量时相同。在 MATLAB 语言中,变量可在运行时动态更改其类、大小或复/实性,所以您可以使用同一个变量存储不同类、大小或复/实性的值。C 和 C++ 使用静态类型。在使用变量之前,为了确定变量的类型,代码生成器需要为每个变量完整赋值。同样,在使用属性之前,您必须显式定义属性的类、大小和复/实性。

  • 初始值:

    • 如果属性没有显式初始值,代码生成器将假定它未在构造函数的起始部分进行定义。代码生成器不会指定空矩阵作为默认值。

    • 如果属性没有初始值,而且代码生成器无法确定该属性在第一次使用之前是否已赋值,软件将会生成编译错误。

    • 对于 System object,如果不可调属性是一个结构体,则必须为该结构体完整赋值。不能使用下标进行部分赋值。

      例如,对于不可调属性,可以使用以下完整赋值语句:

      mySystemObject.nonTunableProperty=struct('fieldA','a','fieldB','b');
      

      但不能使用以下部分赋值语句:

      mySystemObject.nonTunableProperty.fieldA = 'a';
      mySystemObject.nonTunableProperty.fieldB = 'b';

    • 类属性不支持 coder.varsize

    • 如果一个属性的初始值是对象,则该属性必须是常量。要使属性为常量,可在属性模块中声明 Constant 属性。例如:

      classdef MyClass 
          properties (Constant) 
              p1 = MyClass2; 
          end 
      end 

    • MATLAB 会在代码生成之前加载类时计算类的初始值。如果您在 MATLAB 类属性初始化中使用持久变量,则加载类时计算的持久变量的值属于 MATLAB;它不是在代码生成时使用的值。如果您在 MATLAB 类属性初始化中使用 coder.targetcoder.target('MATLAB') 将返回 true (1)

  • 如果启用了动态内存分配,则代码生成支持句柄类的可变大小属性。如果禁用了动态内存分配,则不能为具有可变大小属性的句柄类生成代码。

  • 如果属性是常量,其值是对象,则不能更改该对象的属性值。例如,假设:

    • objmyClass1 的对象。

    • myClass1 有一个常量属性 p1,它是 myClass2 的对象。

    • myClass2 有一个 p2 属性。

    代码生成不支持以下代码:

    obj.p1.p2 = 1;

基类构造函数的调用

如果类构造函数包含对基类构造函数的调用,则对基类构造函数的调用必须出现在 forifreturnswitchwhile 语句之前。

例如,如果您基于类 A 定义类 B

classdef B < A
    methods
        function obj = B(varargin)
            if nargin == 0
                a = 1;
                b = 2;
            elseif nargin == 1
                a = varargin{1};
                b = 1;
            elseif nargin == 2
                a = varargin{1};
                b = varargin{2};
            end
            obj = obj@A(a,b);
        end    
        
    end
end

因为 B 的类定义在调用 A 的基类构造函数之前使用了 if 语句,所以您不能为函数 callB 生成代码:

function [y1,y2] = callB
x = B;
y1 = x.p1;
y2 = x.p2;
end

但是,如果您按如下所示定义类 B,则可以为 callB 生成代码:

classdef B < A
    methods
        function obj = NewB(varargin)
            [a,b] = getaandb(varargin{:});
            obj = obj@A(a,b);
        end
        
    end
end

function [a,b] = getaandb(varargin)
if nargin == 0
    a = 1;
    b = 2;
elseif nargin == 1
    a = varargin{1};
    b = 1;
elseif nargin == 2
    a = varargin{1};
    b = varargin{2};
end
end

不支持从内置 MATLAB 类继承

不能为从内置 MATLAB 类继承的类生成代码。例如,不能为以下类生成代码:

classdef myclass < double