【问题标题】:Matlab coder & dynamic field referencesMatlab 编码器和动态字段参考
【发布时间】:2015-02-16 14:17:26
【问题描述】:

我正在尝试创建一个小解析器,它可以读取包含算法参数的 .txt 文件,这样我就不必每次更改参数时都重新编译它。该应用程序是通过 coder 从 .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 这样的结构的动态字段名。

我有点不知所措,因为我应该如何想出一个参数结构来保存我所有的键值对而不对其进行硬编码。如果键的名称没有动态链接到参数文件(如果添加/删除参数等,则需要更多的手动工作),它会在某种程度上(尽管不完全)破坏目的。如果有人知道如何解决这个问题,我将不胜感激。

【问题讨论】:

    标签: matlab matlab-coder


    【解决方案1】:

    正如您所说,MATLAB 代码中不允许结构的动态字段名供 Coder 使用。我以前也遇到过和你很像的情况,我是这样处理的。

    首先,我们可以列出一些在 Coder 中允许使用的好工具。我们可以有类(值或句柄),这非常方便。此外,如果我们使用coder.varsize 来专门指定它,我们就可以拥有可变大小的数据。如果我们愿意,我们也可以在 switch 语句中使用字符串值。但是,我们不能将 coder.varsize 用于类中的属性,但如果您愿意,您可以使用 varsized 持久变量。

    在您的情况下,我要做的是创建一个句柄类来存储和检索值。以下示例非常基本,但可以使用并且可以扩展。如果在方法中使用了持久变量,您甚至可以为数据创建一个可变大小的分配存储,但在我的示例中,它是一个属性,并且它可以存储的值的数量受到限制。

    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
    

    这个类实现了一个简单的键/值添加以及查找。有几点需要注意。首先,在分配时非常小心,以确保我们不会超出整个存储空间。其次,它使用deblank 清除字符串存储中所需的尾随零。在这种情况下,不允许结构中的字符串具有不同的长度,因此当我们将关键字符串放入其中时,它需要与尾随空值完全相同的长度。 Deblank 为调用函数清理了这个。

    常量属性分配我们在存储阵列中允许的空间总量。显然,这些可以增加,但不能在运行时增加。

    在 MATLAB 命令提示符下,使用此类如下所示:

    >> 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 的持久变量,但这会将此类的使用限制为单个实例。持久变量很好,但你只能得到其中一个。正如所写,您可以在程序的许多不同位置使用此类用于不同的存储。如果使用持久变量,则只能使用一次。

    如果您知道一些键名并在以后使用它们来确定功能,请记住您可以在 MATLAB 中打开字符串,这在 Coder 中有效。

    【讨论】:

    • 我将不得不考虑这个问题,看看它是否真的适合我的应用程序,因为我在 OO 范式中一点也不“流利”,但仍然感谢您的建议!它可能不会出现在我的代码中,因为它正在逐步淘汰以支持 python 项目(无需交叉编译),但希望我能从中学到一些东西。
    猜你喜欢
    • 1970-01-01
    • 2019-01-24
    • 2019-01-01
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 2022-01-02
    • 2012-03-17
    • 2021-08-03
    相关资源
    最近更新 更多