Generate Code That Reads Data from a File
This example shows how to generate C code from your MATLAB® code that reads data from a CSV file and stores the data in a table.
Inspect Data File
The goal of this example is to generate code that reads a comma separated values (CSV) file that contains temperature measurements (in units of degrees Celsius) of a furnace taken at various times over a course of several days. The file begins with several lines of description. This is followed by the data listed as comma-separated values in a table format.
type mydata.csv
Temperature 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
Create and Test MATLAB Entry-Point Function
Write a MATLAB® function my_readtable
that reads the file mydata.csv
, ignores the initial description lines, and creates a MATLAB table
containing the datetime
and numeric values. Because the MATLAB function readtable
is not supported for code generation, this example uses low-level file I/O functions like fopen
, fgetl
, fscanf
, feof
, and fclose
to open the file, read data, and finally close the file.
type my_readtable.m
function 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
This entry-point function (top-level MATLAB function for which you generate code) uses these coding patterns that make it suitable for code generation:
The size of the character vector
line
changes as the function reads each line of the initial description. Thecoder.varsize
directive instructs the code generator to produce code that dynamically allocates memory for the variableline
.The function hardcodes the column header names
'time'
and'temp'
instead of reading them from the CSV file at run time. This is because code generation requires table variable names to be compile-time constants.The variable
months
is defined as a character array instead of a string array because code generation does not support string arrays.The function preinitializes the arrays
dateAndTime
andtemperature
before populating them with actual data (in thewhile
loop).
Run the MATLAB entry-point function.
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
Generate and Run MEX
To test the output of code generation inside the MATLAB environment, generate and run a MEX (MATLAB executable) by using the codegen
command. A MEX is compiled C/C++ code that you can run inside the MATLAB environment. By default, the codegen
command produces a MEX.
In the codegen
command, specify the following data types for the input arguments of the function my_readtable
:
filename
is an unbounded variable-length stringnumRecords
is a double scalar
s = "mystring"; t = coder.typeof(s); t.Properties.Value = coder.typeof('a',[1 inf]); codegen my_readtable -args {t,0} -report
Code generation successful: To view the report, open('codegen/mex/my_readtable/html/report.mldatx')
The code generator produces the MEX function my_readtable_mex
. Run the generated 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
Generate Standalone Code
Generate a static C library for my_readtable
for deployment on target hardware.
codegen -config:lib my_readtable -args {t,0} -report
Code generation successful: To view the report, open('codegen/lib/my_readtable/html/report.mldatx')
The file I/O functions are implemented differently between the MEX and the standalone code. For example, for MEX code generation, the code generator automatically treats fscanf
as an extrinsic function. So, the generated MEX dispatches the fscanf
calls to the MATLAB engine for execution. If you generate standalone code, the code generator actually produces C/C++ code for the body of the MATLAB fscanf
function.
For MEX target, If you want to generate C/C++ code for the body of the MATLAB fscanf
function, disable extrinsic function calls by setting the ExtrinsicCalls
property of the coder.MexCodeConfig
object to false
. Alternatively, in the MATLAB Coder app, on the More Settings tab, set Keep extrinsic calls to No
.
If you have Embedded Coder®, you can verify the generated standalone code by using Software-In-the-Loop (SIL) or Processor-In-the-Loop (PIL) execution before deployment. For an example, see SIL and PIL Verification for Deployment on Raspberry Pi (Embedded Coder).