ファイルからデータを読み取るコードの生成
この例では、ファイルからデータを読み取る MATLAB® 関数から C コードを生成する方法を示します。
データ ファイルの検査
この例では、コンマ区切り値 (CSV) 形式のファイル mydata.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
エントリポイント関数の作成とテスト
データ ファイル mydata.csv を読み取る MATLAB 関数 my_readtable を作成します。関数は最初の説明の行を無視し、datetimeと数値を含む MATLAB tableを作成します。MATLAB 関数readtableはコード生成でサポートされていないため、my_readtable 関数はfopen、fgetl、fscanf、feof、fcloseなどの低水準ファイル I/O 関数を使用してファイルを開き、読み取って、閉じます。
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 ファイルから読み取るのではなくハードコードします。これは、コード生成では 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