用于代码生成的 MATLAB 类定义
要为 MATLAB® 类生成高效的独立代码,必须按照与在 MATLAB 环境中运行代码时不同的方式来使用类。
语言限制
虽然为类的常用功能(例如属性和方法)提供了代码生成支持,但仍有一些高级功能不受支持,例如:
事件
侦听程序
对象数组
递归数据结构体
链表
树
图
构造函数中的嵌套函数
可重载运算符
subsref
、subsassign
和subsindex
在 MATLAB 中,类可以定义自己的
subsref
、subsassign
和subsindex
方法版本。代码生成不支持拥有这些自定义方法的类。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.Constant
或coder.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.target
,coder.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-size. obj.prop = 1:98; obj.varProp = 1:n; end
在上述代码中,对
prop
和varProp
的第一个赋值是标量,第二个赋值是具有相同基类型的数组。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-size column % vector with no size limit coder.varsize('locVar',[inf 1],[1 0]); % Assign value obj.prop = locVar; end end end
在上述代码中,
inVar
传递给类构造函数,并存储在locVar
中。locVar
由coder.varsize
修改为可变大小,并分配给类属性obj.prop
,这使得属性的大小可变。如果函数调用
varSizeProp2
的输入是可变大小的,则不需要coder.varsize
。function z = constructCall(n) z = varSizeProp2(1:n); end
如果
n
的值在编译时未知并且没有指定的界限,则z.prop
是无界的可变大小类属性。如果
n
的值在编译时未知,并且具有指定的界限,则z.prop
是具有上界的可变大小类属性。
如果属性是常量,其值是对象,则不能更改该对象的属性值。例如,假设:
obj
是myClass1
的对象。myClass1
有一个常量属性p1
,它是myClass2
的对象。myClass2
有一个p2
属性。
代码生成不支持以下代码:
obj.p1.p2 = 1;
不支持从内置 MATLAB 类继承
不能为从内置 MATLAB 类继承的类生成代码。例如,不能为以下类生成代码:
classdef myclass < double
此规则的一个例外是 MATLAB 枚举类。您可以为从内置 MATLAB 类继承的枚举类生成代码。请参阅Code Generation for Enumerations。