生成从文件中读取数据的代码
此示例说明如何从读取文件数据的 MATLAB® 函数生成 C 代码。
检查数据文件
在此示例中,您生成代码以读取 mydata.csv,这是逗号分隔值 (CSV) 格式的文件。此文件包含几天内不同时间的炉温(以摄氏度为单位)的测量值。该文件包含几行描述,后跟 CSV 格式的数据。
type mydata.csvTemperature of a furnace in degrees Celsius measured at various times over a course of one week time, temp 19-Aug-2021 10:32:35, 81 20-Aug-2021 10:40:28, 72 22-Aug-2021 10:19:36, 98 23-Aug-2021 11:00:02, 70 24-Aug-2021 10:54:27, 90 25-Aug-2021 11:03:00, 87
创建并测试入口函数
创建一个 MATLAB 函数 my_readtable 以读取数据文件 mydata.csv。该函数忽略初始描述行,并创建一个包含 datetime 和数值的 MATLAB table。由于代码生成不支持 MATLAB 函数 readtable,my_readtable 函数使用低级文件 I/O 函数(如 fopen、fgetl、fscanf、feof 和 fclose)打开、读取和关闭文件。
type my_readtable.mfunction T = my_readtable(filename,numRecords) %#codegen
f = fopen(filename,"r");
% Scan and ignore a variable number of description lines at the beginning
% of the CSV file.
line = fgetl(f);
coder.varsize("line");
while(~ismember(',',line))
line = fgetl(f);
end
% Table variable names.
names = {'time' 'temp'};
% Initialize variables. Define 'months' cell array that is used to convert
% name of month to serial number of month in the next code block.
i = 1;
months = {'Jan' 'Feb' 'Mar' 'Apr' 'May' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov' 'Dec'};
dateAndTime = repmat(datetime,1,numRecords);
temperature = zeros(1,numRecords);
% Read each line in the CSV file till you reach EOF. Construct an array of
% datetime and double values (for time and temp columns).
while(~feof(f))
day = fscanf(f,'%u-');
month_name = string(fscanf(f,'%3c',1));
month_number = find(month_name == months);
[result,count] = fscanf(f,'-%u %u:%u:%u, %u');
% Check that the last fscanf call read all remaining data in the line
assert(count == 5)
year = result(1);
hour = result(2);
minute = result(3);
second = result(4);
dateAndTime(i) = datetime(year,month_number,day,hour,minute,second);
temperature(i) = result(5);
i = i + 1;
end
% Construct the table from the values read in the previous code block.
T = table(dateAndTime',temperature','VariableNames',names);
fclose(f);
end
此入口函数(您为其生成代码的顶层 MATLAB 函数)使用这些编码模式,使其适合代码生成:
字符向量
line的大小随着函数读取初始描述的每行而变化。coder.varsize指令指示代码生成器生成为变量line动态分配内存的代码。该函数对列标题名称
'time'和'temp'进行硬编码,而不是在运行时从 CSV 文件中读取它们。这是因为代码生成要求表变量名称是编译时常量。变量
months定义为字符数组而不是字符串数组,因为代码生成不支持字符串数组。该函数在
while循环中对数组dateAndTime和temperature填充实际数据之前对其预初始化。
运行 MATLAB 入口函数。
T_matlab = my_readtable("mydata.csv",6)T_matlab=6×2 table
time temp
____________________ ____
19-Aug-2021 10:32:35 81
20-Aug-2021 10:40:28 72
22-Aug-2021 10:19:36 98
23-Aug-2021 11:00:02 70
24-Aug-2021 10:54:27 90
25-Aug-2021 11:03:00 87
使用 MEX 函数测试生成的代码
要在 MATLAB 环境中测试代码生成的输出,请生成并运行 MEX(MATLAB 可执行文件)函数。MEX 函数是在 MATLAB 环境中运行的已编译 C/C++ 函数。在命令行中使用 codegen 命令生成一个 MEX 函数。
在 codegen 命令中,为函数 my_readtable 的输入参量指定以下数据类型:
filename是无界可变长度字符串numRecords是双精度标量
s = "mystring"; t = coder.typeof(s); t.Properties.Value = coder.typeof('a',[1 inf]); codegen my_readtable -args {t,0} -report
Code generation successful: View report
代码生成器生成 MEX 函数 my_readtable_mex。使用用于测试 MATLAB 函数的相同值来运行生成的 MEX 函数。
T_mex = my_readtable_mex("mydata.csv",6)T_mex=6×2 table
time temp
____________________ ____
19-Aug-2021 10:32:35 81
20-Aug-2021 10:40:28 72
22-Aug-2021 10:19:36 98
23-Aug-2021 11:00:02 70
24-Aug-2021 10:54:27 90
25-Aug-2021 11:03:00 87
生成独立 C 代码。
使用 codegen 命令为 my_readtable 生成静态 C 库。生成的库可以部署在目标硬件上。
codegen -config:lib my_readtable -args {t,0} -report
Code generation successful: View report
文件 I/O 函数在 MEX 函数和独立代码中的实现方式不同。例如,在 MEX 代码生成期间,代码生成器自动将 fscanf 视为外部函数。这意味着生成的 MEX 函数将 fscanf 调用调度给 MATLAB 引擎来执行。相反,当您生成独立代码时,代码生成器为 fscanf 函数的主体生成 C/C++ 代码。
如果您生成 MEX 函数,但希望为外部函数生成 C/C++ 代码,请通过将 coder.MexCodeConfig 对象的 ExtrinsicCalls 属性设置为 false 来禁用外部函数调用。或者,在“代码生成设置”对话框中,清除Keep extrinsic calls参数。
如果您有 Embedded Coder®,可以在部署前使用软件在环 (SIL) 或处理器在环 (PIL) 执行来验证生成的独立代码。请参阅SIL and PIL Verification for Deployment on Raspberry Pi (Embedded Coder)。
另请参阅
load | save | coder.load | coder.read | coder.write