ファイルからデータを読み取るコードの生成
この例では、CSV ファイルからデータを読み取って table に保存する MATLAB® コードから C コードを生成する方法を示します。
データ ファイルの検査
この例の目標は、数日間にわたってさまざまな時刻に取得された炉の温度の測定値 (摂氏単位) を含むコンマ区切り値 (CSV) ファイルを読み取るコードを生成することです。このファイルの先頭には数行の説明があります。この後に、データが table 形式のコンマ区切り値としてリストされています。
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
MATLAB エントリポイント関数の作成とテスト
ファイル mydata.csv
を読み取って最初の説明行を無視し、datetime
と数値を含む MATLAB table
を作成する MATLAB® 関数 my_readtable
を記述します。MATLAB 関数readtable
はコード生成でサポートされていないため、この例ではfopen
、fgetl
、fscanf
、feof
、fclose
などの低水準ファイル I/O 関数を使用してファイルを開き、データを読み取って、最後にファイルを閉じます。
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
このエントリポイント関数 (コードを生成する最上位の MATLAB 関数) では、関数をコード生成に適したものにする次のコーディング パターンを使用します。
関数によって最初の各説明行が読み取られると、文字ベクトル
line
のサイズが変化します。coder.varsize
命令により、コード ジェネレーターは、変数line
のメモリを動的に割り当てるコードを生成します。関数は、列ヘッダー名
'time'
および'temp'
を、実行時に CSV ファイルから読み取るのではなくハードコードします。これは、コード生成では table 変数名がコンパイル時の定数である必要があるためです。コード生成では string 配列がサポートされないため、変数
months
は string 配列ではなく文字配列として定義されます。関数は、配列
dateAndTime
およびtemperature
を事前に初期化してから、それらの配列に実際のデータを格納します (while
ループ内)。
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 環境内でコード生成の出力をテストするには、codegen
コマンドを使用して MEX (MATLAB 実行可能ファイル) を生成し実行します。MEX は、MATLAB 環境内で実行できるコンパイル済み C/C++ コードです。既定では、codegen
コマンドは MEX を生成します。
codegen
コマンドで、関数 my_readtable
の入力引数に次のデータ型を指定します。
filename
は制限のない可変長 stringnumRecords
は double スカラー
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')
コード ジェネレーターが MEX 関数 my_readtable_mex
を生成します。生成された 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
スタンドアロン コードの生成
ターゲット ハードウェアに展開する my_readtable
の静的な C ライブラリを生成します。
codegen -config:lib my_readtable -args {t,0} -report
Code generation successful: To view the report, open('codegen/lib/my_readtable/html/report.mldatx')
ファイル I/O 関数の実装は MEX とスタンドアロン コードで異なります。たとえば、MEX コード生成では、コード ジェネレーターは自動的に fscanf
を外部関数として扱います。そのため、生成された MEX は、実行のために MATLAB エンジンの fscanf
呼び出しをディスパッチします。スタンドアロン コードを生成する場合、コード ジェネレーターは MATLAB 関数 fscanf
の本体の C/C++ コードを実際に生成します。
MEX ターゲットで、MATLAB 関数 fscanf
の本体の C/C++ コードを生成する場合は、coder.MexCodeConfig
オブジェクトの ExtrinsicCalls
プロパティを false
に設定して外部関数呼び出しを無効にします。あるいは、MATLAB Coder アプリの [詳細設定] タブで、[外部呼び出しを維持] を No
に設定します。
Embedded Coder® を利用している場合、展開前にソフトウェアインザループ (SIL) またはプロセッサインザループ (PIL) 実行を使用して、生成されたスタンドアロン コードを検証できます。例については、SIL and PIL Verification for Deployment on Raspberry Pi (Embedded Coder)を参照してください。