MATLAB Coder アプリを使用した C コードの生成
このチュートリアルでは、MATLAB® Coder™ アプリを使用して MATLAB 関数の C ソース コードを生成します。最初に、固定の既定サイズの入力のみを受け入れる C コードを生成します。その後、複数の異なるサイズの入力を受け入れる C コードを生成します。
コードは MATLAB コマンド ラインで codegen
コマンドを使用して生成することもできます。チュートリアルについては、コマンド ラインでの C コードの生成を参照してください。
MATLAB Coder では、スクリプトではなく MATLAB 関数からコードが生成されます。MATLAB コードがスクリプトの形式の場合は、コードを生成する前にスクリプトのラッパー関数を作成します。
チュートリアル ファイル: ユークリッド距離
この例を開いて、このチュートリアルのファイルを取得します。
チュートリアル ファイルの説明
このチュートリアルで使用するファイルは、euclidean_data.mat
、euclidean.m
、および euclidean_test.m
です。
MATLAB データ ファイル
euclidean_data.mat
には、2 つのデータが格納されています。x
は、3 次元ユークリッド空間の点を表す3
行1
列の列ベクトルです。cb
は、3
行216
列の配列です。cb
の各列が 3 次元ユークリッド空間の点を表します。
MATLAB ファイル
euclidean.m
には、この例のコア アルゴリズムを実装する関数euclidean
が含まれています。この関数はx
とcb
を入力として受け取り、x
とcb
の各点の間のユークリッド距離を計算して次の量を返します。列ベクトル
y_min
。x
に最も近い点を表すcb
の列と等しくなります。列ベクトル
y_max
。x
から最も遠い点を表すcb
の列と等しくなります。2 次元のベクトル
idx
。ベクトルy_min
とy_max
のcb
における列インデックスが格納されます。2 次元のベクトル
distance
。x
との間の計算された最短距離と最長距離が格納されます。
function [y_min,y_max,idx,distance] = euclidean(x,cb) % Initialize minimum distance as distance to first element of cb % Initialize maximum distance as distance to first element of cb idx(1)=1; idx(2)=1; distance(1)=norm(x-cb(:,1)); distance(2)=norm(x-cb(:,1)); % Find the vector in cb with minimum distance to x % Find the vector in cb with maximum distance to x for index=2:size(cb,2) d=norm(x-cb(:,index)); if d < distance(1) distance(1)=d; idx(1)=index; end if d > distance(2) distance(2)=d; idx(2)=index; end end % Output the minimum and maximum distance vectors y_min=cb(:,idx(1)); y_max=cb(:,idx(2)); end
MATLAB スクリプト
euclidean_test.m
は、データ ファイルeuclidean_data.mat
をワークスペースに読み込みます。その後、関数euclidean
を呼び出してy_min
、y_max
、idx
、およびdistance
を計算します。このスクリプトで計算された量がコマンド ラインに表示されます。euclidean_data.mat
の読み込みは、コア アルゴリズムを呼び出す前に実行される事前処理のステップです。結果の表示は事後処理のステップとなります。% Load test data load euclidean_data.mat % Determine closest and farthest points and corresponding distances [y_min,y_max,idx,distance] = euclidean(x,cb); % Display output for the closest point disp('Coordinates of the closest point are: '); disp(num2str(y_min')); disp(['Index of the closest point is ', num2str(idx(1))]); disp(['Distance to the closest point is ', num2str(distance(1))]); disp(newline); % Display output for the farthest point disp('Coordinates of the farthest point are: '); disp(num2str(y_max')); disp(['Index of the farthest point is ', num2str(idx(2))]); disp(['Distance to the farthest point is ', num2str(distance(2))]);
ヒント
テスト スクリプトを使用して、コア アルゴリズムを実装する関数から事前処理と事後処理のステップを分割します。こうすることで、アルゴリズムを簡単に再利用できます。ここでは、コア アルゴリズムを実装する MATLAB 関数のコードを生成します。テスト スクリプトのコードは生成しません。
MATLAB 関数の C コードの生成
MATLAB Coder アプリを使用して、関数 euclidean
の C ソース コードを生成します。この手順で生成するコードは、固定の既定サイズの入力のみを受け入れます。
元の MATLAB コードの実行
テスト スクリプト euclidean_test.m
を実行します。y
、idx
、および distance
が出力に表示されます。
Coordinates of the closest point are: 0.8 0.8 0.4 Index of the closest point is 171 Distance to the closest point is 0.080374 Coordinates of the farthest point are: 0 0 1 Index of the farthest point is 6 Distance to the farthest point is 1.2923
コード生成用の MATLAB コードの準備
MATLAB エディターのコード アナライザーは、コードの入力時にそれを常にチェックします。コード アナライザーは、コードの問題を報告し、パフォーマンスと保守性を最大化するための修正方法を提案します。
MATLAB エディターで、
euclidean.m
を開きます。MATLAB エディターの右上隅にあるコード アナライザー メッセージ インジケーターは緑色になります。アナライザーは、コード内にエラー、警告または改善すべき点を検出しませんでした。関数宣言の後に、
%#codegen
命令を追加します。function [y,idx,distance] = euclidean(x,cb) %#codegen
%#codegen
命令により、コード生成に固有の警告やエラーがコード アナライザーで特定されます。コード アナライザー メッセージ インジケーターが赤色になり、コード生成の問題が検出されたことが示されます。
警告メッセージを表示するには、下線が引かれているコード部分をポイントします。この警告は、コードを生成するには、変数
idx
とdistance
を完全に定義してから添字を付けなければならないことを示しています。これらの警告が発生するのは、コード ジェネレーターが変数のサイズをコードにおける最初の出現箇所で決定するためです。この問題を修正するには、関数ones
を使用して、それらの配列の割り当てと初期化を同時に行います。idx = ones(1,2); distance = ones(1,2)*norm(x-cb(:,1));
コード アナライザーで [エラーが見つかりませんでした] アイコンが表示され、コード生成に関する問題がほかに検出されていないことが示されます。
コード アナライザーの使用の詳細については、コード アナライザーを使用したエラーと警告についてのコードのチェックを参照してください。
ファイルを保存します。
これで、MATLAB Coder アプリを使用してコードをコンパイルする準備ができました。
メモ
MATLAB Coder では、MATLAB コードの "コンパイル" とは、MATLAB コードから C/C++ コードを生成することを指します。他のコンテキストでは、コンパイルという用語は C/C++ コンパイラのアクションを指します。
MATLAB Coder アプリを開いてプロジェクト ファイルを作成
MATLAB Coder アプリを使用してコードを生成するには、拡張子 .coderprj
をもつ MATLAB Coder プロジェクト ファイルを最初に作成しなければなりません。このファイルに、MATLAB Coder エントリポイント関数のパス、それらの入力の型、グローバル変数、コード生成構成パラメーターなど、コード ジェネレーターに提供する情報が格納されます。
MATLAB ツールストリップの [アプリ] タブの [コード生成] で [MATLAB Coder] をクリックします。アプリの [MATLAB Coder プロジェクトの作成] ダイアログ ボックスが開きます。
プロジェクト ファイルの名前と、ファイルを保存するフォルダーを指定します。この例では、現在の作業フォルダーに
euclidean.coderprj
という名前のファイルを作成します。
[MATLAB Coder] ツールストリップ タブが開きます。タブの各セクションは、C/C++ コード生成用の MATLAB コードの準備、コードの生成、生成コードの検証の実行、コード生成レポートの表示、生成コードのエクスポートなど、コード生成時に実行するさまざまな手順にそれぞれ対応しています。
さらに、[MATLAB Coder] パネルが開きます。[次のステップ] セクションにコード生成手順を案内するメッセージが表示され、[入力] セクションと [出力] セクションにコード生成の入力と出力の要約が示されます。
MATLAB エントリポイント関数の指定
"エントリポイント関数" は、コードを生成する最上位の MATLAB 関数です。この例では、エントリポイント関数は euclidean
です。
[MATLAB Coder] パネルの [次のステップ] セクションに、空のプロジェクトにエントリポイントを追加しなければならないことが示されます。
エントリポイント関数を追加するには、次のようにします。
[MATLAB Coder] パネルの [入力] セクションにある [エントリ ポイントの追加] ボタンをクリックするか、ツールストリップの [エントリ ポイント] ボタンをクリックします。
[エントリ ポイント] タブが開きます。エントリポイント関数の名前
euclidean
を入力します。
エントリポイント関数について、アプリでコード生成の準備状態ツールが実行されます。このツールでは、MATLAB コード内にコード生成でサポートされない機能や関数がないかどうかを調べることができます。エントリポイント関数またはその依存関係のいずれかに問題が見つかった場合、[エントリ ポイント] タブに警告メッセージが表示されます。メッセージの横にあるリンクをクリックするとコード生成の準備状態ツールが別のウィンドウで開き、そのウィンドウで問題を確認して修正できます。この例では、euclidean
関数においてコード生成の準備状態の問題は検出されません。詳細については、コード生成の準備状態ツールを参照してください。
メモ
コード アナライザーとコード生成の準備状態ツールで、コード生成に関するすべての問題を検出できるわけではありません。これらの 2 つのツールで検出されたエラーや警告を解決したら、MATLAB Coder でコードを生成し、MATLAB コードに準拠違反の問題がほかにないかどうかを調べてください。
C/C++ コード生成でサポートされる MATLAB の一部の関数とオブジェクトには、特定のコード生成の制限があります。それらの制限と関連する使用上の注意事項については、該当するリファレンス ページの拡張機能のセクションに記載されています。詳細については、C/C++ コードの生成でサポートされている関数およびオブジェクトを参照してください。
入力の型の定義
C/C++ では静的型付けが使用されるため、コード ジェネレーターは MATLAB ファイル内の変数のクラス、サイズ、およびその他のプロパティ (実数/複素数など) をコード生成時 ("コンパイル時") に判別しなければなりません。したがって、エントリポイント関数に対するすべての入力のプロパティを指定しなければなりません。入力のプロパティを指定するために、次の操作が可能です。
次の方法で、入力のプロパティをアプリで自動的に決定するように指示します。
エントリポイント関数を呼び出すスクリプトとサンプル入力を提供します。
エントリポイント関数をサンプル入力を用いて実行するコマンドをコマンド ウィンドウで実行します。
プロパティを直接指定します。
この例では、入力 x
と cb
のプロパティを定義するために、コード ジェネレーターが型を自動的に定義するために使用できるテスト ファイル euclidean_test.m
を指定します。
[エントリ ポイント] タブの上部にある [入力の型を自動的に定義] パラメーターを
[スクリプトの使い方]
に設定します。テスト ファイル
euclidean_test.m
を入力し、実行ボタンをクリックします。
テスト ファイル euclidean_test.m
では、想定された入力の型を用いてエントリポイント関数 euclidean
を呼び出します。アプリは、入力 x
が 3 行 1 列の double
の配列、入力 cb
が 3 行 216 列の double
の配列であると判別します。
MEX 関数の生成と実行
[生成された MEX の実行] ツールストリップ ボタンを使用すると、エントリポイント関数から MEX ファイルが生成され、MEX 関数が実行されて問題が報告されます。MEX 関数は MATLAB 内から呼び出すことができる生成コードです。生成されたスタンドアロンの C/C++ コードでは診断が難しいランタイム エラーを検出して修正できるため、この手順を実行することをお勧めします。既定では、MEX 関数にはメモリ整合性チェックが含まれます。このチェックにより、配列の範囲と次元のチェックが実行されます。このチェックを実行することにより、MATLAB 関数に対して生成されたコード内のメモリ整合性の違反が検出されます。詳細は、実行時チェックの制御を参照してください。
[MATLAB Coder] ツールストリップ タブで [生成された MEX の実行] ドロップダウン メニューを開きます。
エントリポイント関数をサンプル入力を用いて呼び出すテスト ファイルを指定します。この例では、入力の型を定義するために使用したテスト ファイル
euclidean_test.m
を使用します。
アプリにより MEX 関数が生成されます。euclidean
の呼び出しを生成された MEX の呼び出しで置き換えたうえで、テスト スクリプト euclidean_test
が実行されます。MEX 関数の生成または実行中に問題が検出された場合は、コマンド ウィンドウに警告メッセージやエラー メッセージが表示されます。これらのメッセージをクリックして問題のあるコードに移動し、問題を修正します。この例では、問題は検出されず、コード生成パネルの [出力] セクションに次のメッセージが表示されます。
ヒント
MATLAB コードからスタンドアロン C/C++ コードを生成する前に、MEX 関数を生成します。特定の状況において、数値的動作が MATLAB と異なるコードがコード ジェネレーターで生成されることがあります。そのため、生成された MEX 関数を実行して、実行時の動作が MATLAB 関数と同じであることを確認することをお勧めします。生成された MEX 関数の応答が MATLAB とは異なる場合、またはエラーが発生する場合は、スタンドアロン コード生成に進む前にこれらの問題を解決しなければなりません。そうしないと、生成するスタンドアロン コードの信頼性が低くなり、未定義の動作が発生する可能性があります。
C ソース コードの生成
ツールストリップの [MATLAB Coder] タブの [準備] セクションで、[出力タイプ] が [スタティック ライブラリ (.lib)] に設定されていることを確認します。その他のコード構成設定については既定値を使用します。
ツールストリップで [コード生成] ボタンをクリックします。
MATLAB Coder によってプロジェクトの C ソース ファイルが生成され、
フォルダーに格納されます。ここで、work
\codegen\lib\euclidean
はチュートリアル ファイルが含まれているフォルダーです。[出力] セクションにはコード生成に成功したことが示され、生成された出力フォルダーとコード生成レポートへのリンクが表示されます。work
[コード生成レポート] をクリックして、レポート ビューアーでレポートを表示します。コード生成中にコード ジェネレーターでエラーや警告が検出された場合は、レポートに問題の説明と問題がある MATLAB コードへのリンクが表示されます。詳細については、コード生成レポートを参照してください。
[コード生成] ボタンをクリックすると、ソース コードの生成のみが行われ、バイナリを作成するためのソース コードのビルドは行われません。ソース コードの生成とバイナリのビルドの両方を単一の手順で行うには、[コード生成] ドロップダウン メニューを開き、[コードを生成してビルド] オプションを選択します。また、C スタティック ライブラリを生成する代わりに、MEX 関数や他の C/C++ ビルド タイプを生成するように選択することもできます。使用できるコード構成設定は MEX や C/C++ ビルド タイプに応じて異なります。MEX と C/C++ の間でコード生成を切り替える際は、選択に応じて該当する設定を確認します。
MATLAB コードを効率良く動作する C/C++ コードに変換するためにコード ジェネレーターによって行われる最適化により、特定の状況において、元の MATLAB コードと生成後のコードで異なる動作になることがあります。生成されたコードと MATLAB コードの相違点を参照してください。
生成された C コードと元の MATLAB コードとの比較
生成された C コードと元の MATLAB コードを比較するには、C ファイル euclidean.c
と euclidean.m
ファイルを MATLAB エディターで開きます。
euclidean.c
ファイル内の生成されたエントリポイント関数のシグネチャは次のようになります。
void euclidean(const double x[3], const double cb[648], double y_min[3], double
y_max[3], double idx[2], double distance[2])
const double x[3]
は MATLAB コード内の入力 x
に対応します。x
のサイズは 3
で、これは MATLAB コードからコードを生成したときに使用したサンプル入力の合計サイズ (3 行 1 列) に対応します。
const double cb[648]
は MATLAB コード内の入力 cb
に対応します。cb
のサイズは 648
で、これは MATLAB コードからコードを生成したときに使用したサンプル入力の合計サイズ (3 行 216 列) に対応します。この例の生成されたコードでは、1 次元配列を使用して MATLAB コードの 2 次元配列を表します。
生成されたコードには、4 つの追加の入力引数があります。配列 y_min
、y_max
、idx
、および distance
です。これらの配列は出力値を返すために使用されます。これらは、元の MATLAB コードの出力引数 y_min
、y_max
、idx
、および distance
に対応します。
コード ジェネレーターでは関数名とコメントが保持されます。変数名については、可能であればコード ジェネレーターで保持されます。
メモ
MATLAB コード内の変数が定数値に設定された場合、生成された C コード内では変数としては表れません。生成された C コード内では、変数の実際の値が含まれています。
Embedded Coder® では、MATLAB コードと生成された C/C++ コードを対話形式でトレースできます。Interactively Trace Between MATLAB Code and Generated C/C++ Code (Embedded Coder)を参照してください。
可変サイズ入力の C コードの生成
euclidean.c
の C 関数は、コード生成時に指定したサンプル入力と同じサイズの入力のみを受け入れます。ただし、対応する MATLAB 関数への入力配列は任意のサイズにすることができます。
ここでは、生成される C コードの x
と cb
の次元について、プロパティを次のように設定するとします。
x
とcb
の両方の最初の次元を最大サイズ3
の可変にします。x
の 2 番目の次元を値1
の固定にします。cb
の 2 番目の次元を最大サイズ216
の可変にします。
これらの入力プロパティを指定するには、次のようにします。
[エントリ ポイント] タブの [入力の型を自動的に定義] でテスト ファイル
euclidean_test.m
を入力し、実行ボタンをクリックします。テスト ファイルでは、想定された入力の型を用いてエントリポイント関数euclidean
を呼び出します。アプリは、入力x
がdouble 3 x 1
、入力cb
がdouble 3 x 216
であると判別します。これらの型では固定サイズの入力が指定されています。euclidean
関数のセクションで、3 列目にあるサイズ指定をクリックします。入力のサイズの編集に使用できるドロップダウン メニューが開きます。:
プレフィックスを使用して、指定された制限までの可変サイズを指定できます。たとえば、:3
は、対応する次元が最大3
までの可変サイズであることを意味します。x
の型をdouble :3 x 1
、cb
の型をdouble :3 x :216
に変更します。
前と同じ手順でコードを生成します。euclidean.c
の生成された C コードの関数シグネチャは次のようになります。
void euclidean(const double x_data[], const int x_size[1], const double cb_data[],
const int cb_size[2], double y_min_data[], int y_min_size[1],
double y_max_data[], int y_max_size[1], double idx[2], double
distance[2])
x_data
、cb_data
、y_min_data
、および y_max_data
は、元の MATLAB 関数の入力引数 x
と cb
および出力引数 y_min
と y_max
に対応します。これで、x_data
、cb_data
、y_min_data
、および y_max_data
のサイズを実行時に指定する 4 つの追加の入力引数 x_size
、cb_size
、y_min_size
、および y_max_size
を C 関数が受け入れるようになります。