代码生成的字典限制
当您在用于代码生成的 MATLAB® 代码中使用 dictionary
时,在某些情况下(例如使用字符串、元胞或结构体时)需要考虑一些注意事项和限制。dictionary
是一种将数据存储为值的数据结构体,您可以使用对应的键来访问这些值。这种类型的数据结构体也称为哈希映射。有关 MATLAB 中字典的详细信息,请参阅Map Data with Dictionaries。要了解字典的代码生成,请参阅为字典生成代码。
在字典中使用字符串
不能通过将字符串数组传递给 dictionary
函数来创建字典。例如,以下函数的代码生成失败了,因为输入参量 Products
是字符串数组。
function out = stringDictError Products = ["Tomato" "Carrot" "Mango" "Mushroom"]; Prices = [1 .5 2.50 1.99]; out = dictionary(Products,Prices) end
要在创建字典时包含字符串类型的键或值,请在 dictionary
函数中指定键-值对组。例如:
function out = stringDictExample1 out = dictionary("Tomato",1,"Carrot",.5,"Mango",2.5,"Mushroom",1.99); end
或者,将字符串键或值单独添加到现有字典中。例如:
function out = stringDictExample2 d = configureDictionary("string","double"); d("Tomato") = 1; d("Carrot") = .5; d("Mango") = 2.5; d("Mushroom") = 1.99; out = d; end
在字典中使用元胞
MATLAB 字典要求所有键和值均为标量。此外,所有键或值必须具有相同的数据类型。不过,通过将数据放在元胞数组中,您可以在一个字典中存储多种数据类型。元胞数组的每个元素都可以包含任何类型或大小的数据,并且您可以在创建字典后将包含不同类型和大小的数据的元胞数组添加到字典中。相反,代码生成器会固定元胞数组中的数据类型,并在字典创建时确定元胞数组中的数据大小是否变化。
元胞数组必须包含相同的数据类型模式
如果使用元胞数组作为键或值,元胞数组中的数据必须在所有条目中遵循相同的数据类型模式。例如,以下函数的代码生成失败了,因为与键 "MyAlphaNum1"
对应的元胞数组值包含字符向量,后跟数值数组;但与键 "MyAlphaNum2"
对应的元胞数组包含数值数组,后跟字符向量。
function out = cellDictError d = dictionary("MyAlphaNum1",{{'abcd',[1 2 3 4]}}); d("MyAlphaNum2") = {{[5 6 7 8],'efgh'}}; out = d; end
function out = cellDictExample d = dictionary("MyAlphaNum1",{{'abcd',[1 2 3 4]}}); d("MyAlphaNum2") = {{'efgh', [5 6 7 8]}}; out = d; end
元胞数组的大小要么是固定的,要么是可变的
创建字典时,代码生成器必须确定元胞数组的内容是固定大小还是可变大小。如果使用元胞数组作为键或值来创建一个具有单个条目的字典,则该元胞数组中元素的大小是固定的,并且以后无法添加具有不同大小元素的元胞数组。要更改元胞数组键或值中数据的大小,必须在创建字典时指定这些数据的大小可变。例如,以下函数的代码生成失败了,因为代码生成器期望每个添加的字典值均为包含 1×3 数值向量的元胞数组。
function out = cellDictVarSizeError1 d = dictionary(1,{[1 2 3]}); d(2) = {[2]}; d(3) = {[5 6 7 8 9]}; out = d; end
同样,如果使用包含相同大小数据的元胞数组创建一个字典,该元胞数组中元素的大小是固定的,以后无法添加不同大小的元素。例如,以下函数的代码生成失败了,因为代码生成器期望每个添加的字典值均为包含 1×3 数值向量的元胞数组。
function out = cellDictVarSizeError2 d = dictionary(1,{[1 2 3]},4,{[10 11 12]}); d(2) = {[2]}; d(3) = {[5 6 7 8 9]}; out = d; end
要指示代码生成器允许元胞数组中的数据大小可变,请在用于创建字典的元胞数组中包含不同大小的数据。例如:
function out = cellDictVarSizeExample1 d = dictionary(1,{[1 2 3]},2,{[4]}); d(3) = {[5 6 7 8 9]}; out = d; end
您也可以使用 coder.varsize
(MATLAB Coder) 显式指示代码生成器允许元胞数组中的数据改变大小。
function out = cellDictVarSizeExample2 value = 1:3; coder.varsize("value",[1 inf]) d = dictionary(1,{value}); d(2) = {[4]}; d(3) = {[5 6 7 8 9]}; out = d; end
不要使用花括号 {}
对字典进行索引
在 MATLAB 中,您可以使用花括号 {}
来查找存储为字典值的元胞的内容,并向包含元胞值的字典中插入新条目。代码生成不支持使用花括号来访问或插入字典值。例如,以下函数的代码生成失败。
function out = dictBraceError d = dictionary("MyAlphaNum1",{{'abcd',[1 2 3 4]}}); d{"MyAlphaNum2"} = {'efgh',[5 6 7 8]}; out = d{"MyAlphaNum2"}; end
要访问或插入元胞数组值,请使用括号 ()
。例如:
function out = dictBraceExample d = dictionary("MyAlphaNum1",{{'abcd',[1 2 3 4]}}); d("MyAlphaNum2") = {{'efgh',[5 6 7 8]}}; val = d("MyAlphaNum2"); out = val{1}; end
在字典中使用结构体
用作键或值的结构体必须具有相同的字段
代码生成支持作为键和值的结构体。但是,在所有字典条目中,键或值结构体必须包含具有相同数据类型的相同字段。例如,函数 structDictError
的代码生成失败有两个原因:首先,键 "Lakeside"
的结构体值缺失 Location
字段。其次,字段 "Phone"
的数据类型在第一个条目中是 uint32
,在第二个条目中是 double
。
function out = structDictError d = dictionary("Apple Hill",struct("Location","Headquarters", ... "City","Natick","Phone",uint32(6477000))); d("Lakeside") = struct("City","Natick","Phone",0); out = d; end
structDictExample
的代码生成成功,因为所有结构体值都包含具有相同数据类型的相同字段。function out = structDictExample d = dictionary("Apple Hill",struct("City","Natick","Phone",uint32(6477000))); d("Lakeside") = struct("City","Natick","Phone",uint32(0)); out = d; end
结构体字段或者都为固定大小,或者都为可变大小
创建字典时,代码生成器必须确定结构体字段的内容是固定大小还是可变大小。如果使用结构体作为键或值来创建一个具有单个条目的字典,则该结构体的字段大小是固定的,并且以后无法添加具有不同大小字段的结构体。要在一个字典中使用具有可变大小字段的结构体,必须在创建该字典时指定字段的大小可变。例如,以下函数的代码生成失败,因为代码生成器期望每个添加的值是具有字段 Address
的结构体,该字段是 1×18 字符串。
function out = structDictVarSizeError d = dictionary("Apple Hill",struct("Address","1 Apple Hill Drive")); d("Lakeside") = struct("Address","1 Lakeside Campus Drive"); d("Novi") = struct("Address","28125 Cabot Drive"); out = d; end
要指示代码生成器允许结构体字段改变大小,请在字典创建命令中包含不同大小的字段。例如:
function out = structDictVarSizeExample d = dictionary("Apple Hill",struct("Address","1 Apple Hill Drive"), ... "Lakeside",struct("Address","1 Lakeside Campus Drive")); d("Novi") = struct("Address","28125 Cabot Drive"); out = d; end
其他约束和限制
在用于代码生成的 MATLAB 代码中使用字典时,请遵守以下附加限制:
不要使用对象(例如用户编写的类和
fi
对象)作为键。不要使用函数句柄或分类数据作为键或值。
不要禁用动态内存分配。
如果使用
configureDictionary
创建一个字典,则该字典不能包含复数作为键或值。要配置可以包含复数的字典,请使用dictionary
函数。如果通过将实数键和值与
dictionary
函数结合使用或通过使用configureDictionary
函数来配置实数值类型的字典,则该字典只能包含实数值类型。代码生成不支持向这样的字典添加复数键或值。即使字典在代码生成时为常量,代码生成器也不会将该字典视为常量。您不能将字典传递给
coder.Constant
(MATLAB Coder) 或coder.const
(MATLAB Coder)。此外,所有字典访问函数,包括lookup
、entries
、keys
和values
,都返回非常量值。这意味着您不能将字典、字典键或字典值传递给需要常量输入的函数。您不能将字典、字典键或字典值用于需要常量的操作,如对异构元胞数组进行索引。代码生成器也无法对字典执行依赖常量值的优化,如常量折叠。不要使用未配置的字典作为入口函数的输入。
不要将未配置的字典传递给
coder.typeof
(MATLAB Coder) 函数。不要使用
configureDictionary
来创建包含以元胞、结构体或用户定义的类作为键或值的字典。