Main Content

用于代码生成的 MATLAB 类定义

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

语言限制

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

  • 事件

  • 侦听程序

  • 对象数组

  • 递归数据结构体

    • 链表

  • 构造函数中的嵌套函数

  • 可重载运算符 subsrefsubsassignsubsindex

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

  • empty 方法

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

  • 以下 MATLAB 句柄类方法:

    • addlistener

    • eq

    • findobj

    • findprop

  • 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 结合使用时,或者当该对象作为常量折叠的外部函数的输入或输出时,代码生成器会对该对象进行常量折叠。

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

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

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

    在多个具有继承关系的类中,重复的属性名称必须为一致的常量或非常量。例如,如果具有常量属性 aProp 的对象从 aProp 定义为非常量的超类继承 aProp,则代码生成会生成错误。

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

为代码生成定义类属性

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

  • MEX 函数报告属性验证产生的错误。独立的 C/C++ 代码仅在启用运行时错误报告时才报告这些错误。请参阅Generate Standalone C/C++ Code That Detects and Reports Run-Time Errors。在生成独立的 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 

      代码生成不支持分配给包含 System object 的对象的常量属性。

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

  • 可变大小属性:

    • 代码生成支持值类和句柄类的有上界和无界的可变大小属性。

    • 要生成无界的可变大小类属性,请启用动态内存分配。

    • 要创建一个可变大小的类属性,需要对类属性先后进行两次赋值,先为标量值,然后是数组。

      classdef varSizeProp1 < handle
          properties
              prop
              varProp
          end
      end
      
      function extFunc(n)
          obj = varSizeProp1;    
          % Assign a scalar value to the property.
          obj.prop = 1;
          obj.varProp = 1;
          % Assign an array to the same property to make it variable-sized.
          obj.prop = 1:98;    
          obj.varProp = 1:n;
      end

      在上述代码中,对 propvarProp 的第一个赋值是标量,第二个赋值是具有相同基类型的数组。prop 的大小有上界 98,使其成为具有上界的可变大小属性。

      如果 n 在编译时未知,则 obj.varProp 是无界的可变大小属性。如果它是已知的,它是具有上界的可变大小类属性。

    • 如果类属性是用可变大小数组初始化的,则属性是可变大小的。

      classdef varSizeProp2 
          properties
              prop
          end
          methods
              function obj = varSizeProp2(inVar)
                  % Assign incoming value to local variable
                  locVar = inVar;
                  
                  % Declare the local variable to be a variable-sized column             
                  % vector with no size limit
                  coder.varsize('locVar',[inf 1],[1 0]);
                  
                  % Assign value
                  obj.prop = locVar;
               end
          end
      end

      在上述代码中,inVar 传递给类构造函数,并存储在 locVar 中。locVarcoder.varsize 修改为可变大小,并分配给类属性 obj.prop,这使得属性的大小可变。

      • 如果函数调用 varSizeProp2 的输入是可变大小的,则不需要 coder.varsize

        function z = constructCall(n)
            z = varSizeProp2(1:n);
        end
      • 如果 n 的值在编译时未知并且没有指定的界限,则 z.prop 是无界的可变大小类属性。

      • 如果 n 的值在编译时未知,并且具有指定的界限,则 z.prop 是具有上界的可变大小类属性。

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

    • objmyClass1 的对象。

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

    • myClass2 有一个 p2 属性。

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

    obj.p1.p2 = 1;

不支持从内置 MATLAB 类继承

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

classdef myclass < double

此规则的一个例外是 MATLAB 枚举类。您可以为从内置 MATLAB 类继承的枚举类生成代码。请参阅Code Generation for Enumerations

另请参阅

相关主题