Matlab错误处理转换为C语言
我想用面向对象的设计来编写一个Matlab代码,然后把它转换成C语言,最后它应该用在DSP处理器上 我不确定的是如何进行错误处理。据我所知,在C语言中应该使用enum,如果我在我的matlab代码中使用exception,我不确定matlab将如何将其转换为C语言 另一种可能性是实现枚举类,并使用它代替异常Matlab错误处理转换为C语言,matlab,architecture,enums,matlab-coder,Matlab,Architecture,Enums,Matlab Coder,我想用面向对象的设计来编写一个Matlab代码,然后把它转换成C语言,最后它应该用在DSP处理器上 我不确定的是如何进行错误处理。据我所知,在C语言中应该使用enum,如果我在我的matlab代码中使用exception,我不确定matlab将如何将其转换为C语言 另一种可能性是实现枚举类,并使用它代替异常 因为我在软件架构方面没有太多经验,所以任何建议都是非常受欢迎的。这是一个相当老的问题,但我认为这是一个相当重要的问题,因为它涉及到一些基本问题,即如何最好地使用MATLAB编码器和构建代码
因为我在软件架构方面没有太多经验,所以任何建议都是非常受欢迎的。这是一个相当老的问题,但我认为这是一个相当重要的问题,因为它涉及到一些基本问题,即如何最好地使用MATLAB编码器和构建代码 一个好的错误处理系统对于任何中等大小的代码库都是非常重要的,因此对其进行结构化非常重要。在针对MATLAB编码器的代码中,您不能使用任何正常的异常函数(try、catch、error等),甚至“assert”在编码器中也有特殊意义。这意味着您需要自己创建一个良好的错误处理系统。这是不幸的,但并非不可逾越 您可以创建一个具有不同错误代码的枚举类型,然后返回相应的枚举。这是一种非常标准的C语言处理方式,它可以非常清晰地从MATLAB转换为C语言。它有几个缺点:
function [ idnum, errorid, errorstring, inneridnum ] = errorcontainer(functionname, varargin ) %#codegen
%ERRORCONTAINER The container function for error processing
% This function contains the error ID table, and can assign new error
% codes or look up error codes.
%
% Examples:
% To register a new error and retrieve a unique error ID:
% idnum = errorcontainter( 'register', ID, MESSAGE )
% where ID and MESSAGE are strings. ID is a short machine readable
% string, and MESSAGE is human-readable.
%
% Optionally, an INNERIDNUM can be provided to indicate an error code for
% a inner (lower-level) error related to this. This will allow
% chaining of error messages:
%
% idnum = errorcontainter( 'register', ID, MESSAGE, inneridnum )
%
% ID and MESSAGE can have maximum lengths of 2048 characters. Anything
% longer will be truncated.
%
% e.g. idnum = errorcontainer('register', ...
% 'FOO_INVALIDTYPE', ...
% 'First input must be an int.');
% idnum will be a negative int32 returned.
%
% If the ID matches an existing ID, the message will be overwritten
% and the same idnum will be returned (the database does not grow).
%
% To lookup an existing error code:
% [idnum, errorid, errorstring] = errorcontainer('lookup', idnum);
%
% See also: errorcode2string, registererror
persistent IDLIST;
persistent ERRORSTRINGLIST;
persistent INNERID;
width = 2048;
if isempty(IDLIST)
IDLIST = char(zeros(1,width));
tempstr = 'ERRORCONTAINER_UNKNOWNERRORID';
IDLIST(1,1:numel(tempstr)) = tempstr;
end
if isempty(ERRORSTRINGLIST)
ERRORSTRINGLIST = char(zeros(1,width));
tempstr = 'Unknown Error';
ERRORSTRINGLIST(1,1:numel(tempstr)) = tempstr;
end
if isempty(INNERID)
INNERID = zeros(1,1,'int32');
end
coder.varsize('IDLIST', 'ERRORSTRINGLIST', 'INNERID', [], [1,1]);
coder.varsize('errorstring', 'errorid');
switch lower(functionname)
case 'register'
% First see if the listed ID matches any in the database.
errorid = varargin{1};
if numel(errorid) > width
errorid = errorid(1:width);
end
if (nargin == 4)
inneridnum = int32(varargin{3});
else
inneridnum = int32(0);
end
errorstring = varargin{2};
if numel(errorstring) > width
errorstring = errorstring(1:width);
end
matchindex = 0;
for i = 1:size(IDLIST,1)
if ( strcmpi(errorid, deblank(IDLIST(i,:))) && (inneridnum == INNERID(i) ) )
matchindex = i;
end
end
if (matchindex > 0)
idnum = int32(-matchindex);
else
idnum = int32(-(size(IDLIST,1)+1));
tempstr = char(zeros(1,width));
tempstr(1:numel(errorid)) = errorid;
IDLIST = [IDLIST ; tempstr]; % In Coder, cannot grow with indexing. Have to concatinte and reassign.
tempstr = char(zeros(1,width));
tempstr(1:numel(errorstring)) = errorstring;
ERRORSTRINGLIST = [ERRORSTRINGLIST ; tempstr];
INNERID = [INNERID; inneridnum];
end
case 'lookup'
idnum = varargin{1};
tidnum = idnum;
if ((-tidnum > size(IDLIST,1)) || (-tidnum <= 0 ))
tidnum = int32(-1);
end
errorid = deblank(IDLIST(-tidnum,:));
errorstring = deblank(ERRORSTRINGLIST(-tidnum,:));
inneridnum = INNERID(-tidnum);
otherwise
idnum = int32(-1);
errorid = deblank(IDLIST(-idnum,:));
errorstring = deblank(ERRORSTRINGLIST(-idnum,:));
inneridnum = int32(0);
end
end
registererror
函数接受一个错误标记字符串(通常是发生错误的函数名,后跟冒号,后跟所发生事件的标识符)和一条人类可读的错误消息。它在全局存储器中注册错误,并将错误标识符作为int32返回。我的代码的规则是,int32(0)的值表示没有错误,负值是这些注册的错误标识符之一
registererror返回的值在每个错误条件下都不是唯一的。它们是错误容器中的引用句柄,可用于检索错误标记字符串和人类可读字符串
在我的代码中,registererror的使用通常是这样的:
...
output = someFunctionThatShouldReturnZeroIfSuccessful(filename);
if (output ~= 0)
result = registerror('MYFUNC:THESOMEFUNCTIONFAILED', ['The function that should return zero returned something else for filename: ', filename]);
return;
end
...
result = registererror('SOMEFUNC:SOMETASK', 'Something terrible happened.')
result = -2
在人类可读的字符串中,我可以从实际执行中附加字符串数据。在本例中,我附加了理论函数中失败的文件名。我将所有函数的返回值设为int32,所有这些值都可以来自对registererror的调用
还有一个对registererror的可选调用。一件很方便的事情是创建一堆错误。有时深层函数中的错误会导致问题,我们需要完整的堆栈跟踪。这很容易做到,因为可以选择将内部错误ID交给registererror。我们来看一个例子:
...
result = someFunctionThatShouldReturnZeroIfSuccessful(filename);
if (result ~= 0)
result = registerror('MYFUNC:THESOMEFUNCTIONFAILED', ['The function that should return zero returned something else for filename: ', filename], result);
return;
end
...
在本例中,someFunction。。。返回一个本身由对registererror的调用生成的值,该结果值作为第三个参数添加到此处的registererror调用,该调用返回一个不同的错误值。我们可以用这个值做什么
嗯,我们需要第三个函数,它通常可以由使用我们的库的代码调用。此函数称为errorcode2string
,顾名思义,它可以获取一个错误代码并返回两个字符串,以及与错误相关的任何内部错误代码。以下是ErrorCode2字符串:
function [errorid, errorstring, innercode] = errorcode2string(errorcode) %#codegen
%ERRORCODE2STRING Return strings given an error code
% Given an error code returned by any of the library functions, will
% return a string with human-readable information about the error. The
% error codes are, in some cases, dynamically generated, so the codes
% themselves should not be used for programmatic flow control except that
% a negative value in a return always indicates an error occurred.
%
% Example:
% [errorid, errorstring, innercode] = errorcode2string(errorcode);
%
% - errorcode is an int32 value.
%
% - errorid is a string that is machine-readable and can be used to trap
% specific error codes.
%
% - errorstring is the returned 1 by N string of the human-readable error
% information.
%
% - innercode is the int32 error code of an inner error message if any.
% It is a negative value of an error code if present, 0 if this is the
% innermost error.
%
% See Also: registererror
[~, errorid, errorstring, innercode] = errorcontainer('lookup', errorcode);
end
正如您所看到的,这个函数实际上只是errorcontainer的一个包装器,但是这样做可以为任何调用库的人保持整洁
例子:
让我们运行一个快速示例。假设一个内部函数失败,调用registererror的方式如下:
...
output = someFunctionThatShouldReturnZeroIfSuccessful(filename);
if (output ~= 0)
result = registerror('MYFUNC:THESOMEFUNCTIONFAILED', ['The function that should return zero returned something else for filename: ', filename]);
return;
end
...
result = registererror('SOMEFUNC:SOMETASK', 'Something terrible happened.')
result = -2
调用函数注意到结果不是0,而是一个负错误代码,它本身抛出一个错误:
result = registererror('CALLINGFUNC:TOPTASK', 'Trying to do some high level thing failed.', result);
result = -3
这个值-3由我们的库返回给调用代码,因此它知道发生错误仅仅是因为结果为负。然后它可以调用errorcode2string来获取有关错误的更多信息
[errorid, errorstring, innercode] = errorcode2string(int32(-3))
errorid = CALLINGFUNC:TOPTASK
errorstring = Trying to do some high level thing failed.
innercode = -2
由于innercode仍然是负数,如果调用程序如此倾向,它可以调用errorcode2string来查找函数堆栈中的更多信息。真的,这就是如何找出发生的根本错误的方法
[errorid, errorstring, innercode] = errorcode2string(int32(-2))
errorid = SOMEFUNC:SOMETASK
errorstring = Something terrible happened.
innercode = 0
现在innercode为0,所以我们知道可以停止
这个系统在我的项目中运行得很好,我希望它能有所帮助。这是我使用Coder首先要解决的问题之一,它教会了我很多关于MATLAB Coder中的良好体系结构实践,包括如何使数据结构具有全局可访问性 使用MATLAB编码器重新标记,该编码器用于C代码生成,而不是MATLAB编译器或部署产品。