Matlab 编码器和动态字段参考
Matlab coder & dynamic field references
我想设计一个小解析器来读取包含算法参数的 .txt 文件,这样我就不必在每次更改参数时都重新编译它。该应用程序是通过编码器从 .m 生成的 C 代码,不幸的是,这禁止我使用很多方便的 matlab 噱头。
到目前为止,这是我的代码:
% read textfile
string = readfile(filepath);
% do fancy rearranging
linebreaks = zeros(size(string));
equals = zeros(size(string));
% find delimiters
for n=1:size(string,2)
if strcmp(string(n),char(10))
linebreaks(n) = 1;
elseif strcmp(string(n), '=')
equals(n) = 1;
end
end
% write first key-value pair
idx_s = find(linebreaks);idx_s = [idx_s length(string)];
idx_e = find(equals);
key = string(1:idx_e(1)-1);
value = str2double(string(idx_e(1)+1:idx_s(1)-1));
parameters.(key) = value;
% find number of parameters
count = length(idx_s);
% write remaining key-value pairs
for n=2:count
key = string(idx_s(n-1)+1:idx_e(n)-1);
value = str2double(string(idx_e(n)+1:idx_s(n)-1));
parameters.(key) = value;
end
问题是编码器似乎不支持 parameters.(key) = value
.
等结构的动态字段名
我有点不知所措,我还应该如何提出一个参数结构来保存我所有的键值对而不对其进行硬编码。如果键的名称没有动态链接到参数文件(如果参数获得 added/deleted 等,则需要更多手动工作),这会有点(虽然不是完全)违背目的。如果有人知道如何解决这个问题,我将不胜感激。
正如您所说,Coder 在 MATLAB 代码中不允许使用结构的动态字段名。我以前遇到过和你很像的情况,下面是我的处理方式。
首先,我们可以列出 Coder 中允许使用的一些不错的工具。我们可以使用 classes(值或句柄),这非常方便。此外,如果我们使用 coder.varsize
来专门指定它,我们就可以拥有可变大小的数据。如果愿意,我们也可以在 switch 语句中使用字符串值。但是,我们不能对 class 中的属性使用 coder.varsize,但如果您愿意,可以使用 varsized 持久变量。
在你的情况下我会做的是创建一个句柄 class 来存储和检索值。以下示例非常基础,但可以工作并且可以扩展。如果在方法中使用持久变量,您甚至可以为数据创建一个可变大小的分配存储,但在我的示例中,它是一个 属性 并且它可以存储的值的数量受到限制。
classdef keyval < handle %# codegen
%KEYVAL A key and value class designed for Coder
% Stores an arbitrary number of keys and values.
properties (SetAccess = private)
numvals = 0
end
properties (Access = private)
intdata
end
properties (Constant)
maxvals = 100;
maxkeylength = 30;
end
methods
function obj = keyval
%KEYVAL Constructor for keyval class
obj.intdata = repmat(struct('key', char(zeros(1, obj.maxkeylength)), 'val', 0), 1, obj.maxvals);
end
function result = put(obj, key, value)
%PUT Adds a key and value pair into storage
% Result is 0 if successful, 1 on error
result = 0;
if obj.numvals >= obj.maxvals
result = 1;
return;
end
obj.numvals = obj.numvals + 1;
tempstr = char(zeros(1,obj.maxkeylength));
tempstr(1,1:min(end,numel(key))) = key(1:min(end, obj.maxkeylength));
obj.intdata(obj.numvals).key = tempstr;
obj.intdata(obj.numvals).value = value;
end
function keystring = getkeyatindex(obj, index)
%GETKEYATINDEX Get a key name at an index
keystring = deblank(obj.intdata(index).key);
end
function value = getvalueforkey(obj, keyname)
%GETVALUEFORKEY Gets a value associated with a key.
% Returns NaN if not found
value = NaN;
for i=1:obj.numvals
if strcmpi(keyname, deblank(obj.intdata(i).key))
value = obj.intdata(i).value;
end
end
end
end
end
这个 class 实现了一个简单的 key/value 添加和查找。有几点需要注意。首先,它在分配时非常小心,以确保我们不会超出整体存储空间。其次,它使用 deblank
清除字符串存储中必需的尾随零。在这种情况下,不允许结构中的字符串具有不同的长度,因此当我们将关键字符串放在那里时,它的长度必须与尾随空值完全相同。 Deblank 为调用函数清理它。
常量属性分配我们在存储阵列中允许的总量 space。显然,这些可以增加,但不能在运行时增加。
在 MATLAB 命令提示符下,使用这个 class 看起来像:
>> obj = keyval
obj =
keyval with properties:
numvals: 0
>> obj.put('SomeKeyName', 1.23456)
ans =
0
>> obj
obj =
keyval with properties:
numvals: 1
>> obj.put('AnotherKeyName', 34567)
ans =
0
>> obj
obj =
keyval with properties:
numvals: 2
>> obj.getvalueforkey('SomeKeyName')
ans =
1.2346
>> obj.getkeyatindex(2)
ans =
AnotherKeyName
>> obj.getvalueforkey(obj.getkeyatindex(2))
ans =
34567
如果需要一个完全可变的存储区域,可以使用带有 coder.varsize 的持久变量,但这会限制此 class 对单个实例的使用。持久变量很好,但你只能得到其中之一。正如所写,您可以在程序的许多不同位置使用此 class 进行不同的存储。如果使用持久变量,则只能使用一次。
如果您知道一些键名并稍后使用它们来确定功能,请记住您可以在 MATLAB 中打开字符串,这在 Coder 中有效。
我想设计一个小解析器来读取包含算法参数的 .txt 文件,这样我就不必在每次更改参数时都重新编译它。该应用程序是通过编码器从 .m 生成的 C 代码,不幸的是,这禁止我使用很多方便的 matlab 噱头。
到目前为止,这是我的代码:
% read textfile
string = readfile(filepath);
% do fancy rearranging
linebreaks = zeros(size(string));
equals = zeros(size(string));
% find delimiters
for n=1:size(string,2)
if strcmp(string(n),char(10))
linebreaks(n) = 1;
elseif strcmp(string(n), '=')
equals(n) = 1;
end
end
% write first key-value pair
idx_s = find(linebreaks);idx_s = [idx_s length(string)];
idx_e = find(equals);
key = string(1:idx_e(1)-1);
value = str2double(string(idx_e(1)+1:idx_s(1)-1));
parameters.(key) = value;
% find number of parameters
count = length(idx_s);
% write remaining key-value pairs
for n=2:count
key = string(idx_s(n-1)+1:idx_e(n)-1);
value = str2double(string(idx_e(n)+1:idx_s(n)-1));
parameters.(key) = value;
end
问题是编码器似乎不支持 parameters.(key) = value
.
我有点不知所措,我还应该如何提出一个参数结构来保存我所有的键值对而不对其进行硬编码。如果键的名称没有动态链接到参数文件(如果参数获得 added/deleted 等,则需要更多手动工作),这会有点(虽然不是完全)违背目的。如果有人知道如何解决这个问题,我将不胜感激。
正如您所说,Coder 在 MATLAB 代码中不允许使用结构的动态字段名。我以前遇到过和你很像的情况,下面是我的处理方式。
首先,我们可以列出 Coder 中允许使用的一些不错的工具。我们可以使用 classes(值或句柄),这非常方便。此外,如果我们使用 coder.varsize
来专门指定它,我们就可以拥有可变大小的数据。如果愿意,我们也可以在 switch 语句中使用字符串值。但是,我们不能对 class 中的属性使用 coder.varsize,但如果您愿意,可以使用 varsized 持久变量。
在你的情况下我会做的是创建一个句柄 class 来存储和检索值。以下示例非常基础,但可以工作并且可以扩展。如果在方法中使用持久变量,您甚至可以为数据创建一个可变大小的分配存储,但在我的示例中,它是一个 属性 并且它可以存储的值的数量受到限制。
classdef keyval < handle %# codegen
%KEYVAL A key and value class designed for Coder
% Stores an arbitrary number of keys and values.
properties (SetAccess = private)
numvals = 0
end
properties (Access = private)
intdata
end
properties (Constant)
maxvals = 100;
maxkeylength = 30;
end
methods
function obj = keyval
%KEYVAL Constructor for keyval class
obj.intdata = repmat(struct('key', char(zeros(1, obj.maxkeylength)), 'val', 0), 1, obj.maxvals);
end
function result = put(obj, key, value)
%PUT Adds a key and value pair into storage
% Result is 0 if successful, 1 on error
result = 0;
if obj.numvals >= obj.maxvals
result = 1;
return;
end
obj.numvals = obj.numvals + 1;
tempstr = char(zeros(1,obj.maxkeylength));
tempstr(1,1:min(end,numel(key))) = key(1:min(end, obj.maxkeylength));
obj.intdata(obj.numvals).key = tempstr;
obj.intdata(obj.numvals).value = value;
end
function keystring = getkeyatindex(obj, index)
%GETKEYATINDEX Get a key name at an index
keystring = deblank(obj.intdata(index).key);
end
function value = getvalueforkey(obj, keyname)
%GETVALUEFORKEY Gets a value associated with a key.
% Returns NaN if not found
value = NaN;
for i=1:obj.numvals
if strcmpi(keyname, deblank(obj.intdata(i).key))
value = obj.intdata(i).value;
end
end
end
end
end
这个 class 实现了一个简单的 key/value 添加和查找。有几点需要注意。首先,它在分配时非常小心,以确保我们不会超出整体存储空间。其次,它使用 deblank
清除字符串存储中必需的尾随零。在这种情况下,不允许结构中的字符串具有不同的长度,因此当我们将关键字符串放在那里时,它的长度必须与尾随空值完全相同。 Deblank 为调用函数清理它。
常量属性分配我们在存储阵列中允许的总量 space。显然,这些可以增加,但不能在运行时增加。
在 MATLAB 命令提示符下,使用这个 class 看起来像:
>> obj = keyval
obj =
keyval with properties:
numvals: 0
>> obj.put('SomeKeyName', 1.23456)
ans =
0
>> obj
obj =
keyval with properties:
numvals: 1
>> obj.put('AnotherKeyName', 34567)
ans =
0
>> obj
obj =
keyval with properties:
numvals: 2
>> obj.getvalueforkey('SomeKeyName')
ans =
1.2346
>> obj.getkeyatindex(2)
ans =
AnotherKeyName
>> obj.getvalueforkey(obj.getkeyatindex(2))
ans =
34567
如果需要一个完全可变的存储区域,可以使用带有 coder.varsize 的持久变量,但这会限制此 class 对单个实例的使用。持久变量很好,但你只能得到其中之一。正如所写,您可以在程序的许多不同位置使用此 class 进行不同的存储。如果使用持久变量,则只能使用一次。
如果您知道一些键名并稍后使用它们来确定功能,请记住您可以在 MATLAB 中打开字符串,这在 Coder 中有效。