ファイルからデータを読み取るコードの生成
この例では、ファイルからデータを読み取る MATLAB® 関数から C コードを生成する方法を示します。
データ ファイルの検査
この例では、コンマ区切り値 (CSV) 形式のファイル mydata.csv
を読み取るコードを生成します。このファイルには、数日間のさまざまな時点における炉の温度 (摂氏単位) の測定値が含まれています。このファイルには、CSV 形式のデータの前に数行の説明が含まれています。
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
エントリポイント関数の作成とテスト
データ ファイル mydata.csv
を読み取る MATLAB 関数 my_readtable
を作成します。関数は最初の説明の行を無視し、datetime
と数値を含む MATLAB table
を作成します。MATLAB 関数readtable
はコード生成でサポートされていないため、my_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 環境内でコード生成の出力をテストするには、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: 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 関数は、実行のために MATLAB エンジンの fscanf
呼び出しをディスパッチします。対照的に、スタンドアロン コードを生成した場合、コード ジェネレーターは fscanf
関数の本体の C/C++ コードを生成します。
MEX 関数を生成するが、外部関数の C/C++ コードも生成する場合は、coder.MexCodeConfig
オブジェクトの ExtrinsicCalls
プロパティを false
に設定して外部関数呼び出しを無効にします。あるいは、[コード生成設定] ダイアログ ボックスで外部呼び出しを維持パラメーターをオフにします。
Embedded Coder® を利用している場合、展開前にソフトウェアインザループ (SIL) またはプロセッサインザループ (PIL) 実行を使用して、生成されたスタンドアロン コードを検証できます。SIL and PIL Verification for Deployment on Raspberry Pi (Embedded Coder)を参照してください。
参考
load
| save
| coder.load
| coder.read
| coder.write