MATLAB Coder アプリを使用した、シンボリック式からの C コードの生成
この例では、MATLAB® Coder™ アプリを使用し、シンボリック式から C スタティック ライブラリを生成する方法を説明します。まず、Symbolic Math Toolbox™ でシンボリック式を処理し、matlabFunction
を使用してそのシンボリック式を展開可能な MATLAB 関数に変換します。次に、この MATLAB 関数から C コードを生成します。生成された C コードは事前に割り当てられた固定サイズの入力を受け入れますが、コード生成時に可変サイズの入力を指定することもできます。
この例は、MATLAB Coder アプリを使用した C コードの生成 (MATLAB Coder)で説明されている手順に従いますが、シンボリック式から MATLAB 関数を生成するための手順が更新されています。または、codegen
(MATLAB Coder)コマンドを使用して、MATLAB コマンド ラインで MATLAB 関数から C コードを生成することもできます。このワークフローのチュートリアルについては、コマンド ラインでの C コードの生成 (MATLAB Coder)を参照してください。
MATLAB Coder アプリは MATLAB Online™ ではサポートされていないことに注意してください。MATLAB Online で C/C++ コードを生成するには、codegen
(MATLAB Coder)コマンドを使用します。
シンボリック式からの展開可能な MATLAB 関数の生成
この例では、次のハミルトニアン モデルの固有値を求めます。
ここで、、 および はハミルトニアンのパラメーターです。
ハミルトニアンのパラメーターを表すシンボリック変数 q
、Omega
および delta
を作成します。ハミルトニアンのシンボリック行列を作成します。
syms q Omega delta H = [(q-1)^2 - delta/2, Omega; Omega, (q+1)^2 + delta/2]
H =
ハミルトニアンの 2 つの固有値を求めます。
E = eig(H)
E =
次に、matlabFunction
を使用して、2 つの固有値 E(1)
および E(2)
を MATLAB 関数ファイルに変換します。得られた関数 (2 つの要素 E1
と E2
を返す関数) を、ファイル myEigenvalues.m
に書き込みます。[q Omega delta]
の順序で入力引数を指定します。
matlabFunction(E(1),E(2),'File','myEigenvalues', ... 'Vars',[q Omega delta],'Outputs',{'E1','E2'});
ファイル myEigenvalues.m
内の変換された関数は Symbolic Math Toolbox なしで使用できます。MATLAB ファイル myEigenvalues.m
には、この例でコアとなるアルゴリズムを実装する関数 myEigenvalues
が含まれています。この関数は、入力として q
、Omega
および delta
を取ります。これらはすべて、同じサイズまたはスカラーでなければなりません。その後、これらの入力の関数として 2 つの固有値が計算されます。
type myEigenvalues
function [E1,E2] = myEigenvalues(q,Omega,delta) %myEigenvalues % [E1,E2] = myEigenvalues(Q,Omega,DELTA) % This function was generated by the Symbolic Math Toolbox version 24.1. % 07-Mar-2024 17:57:45 t2 = Omega.^2; t3 = delta.^2; t4 = q.^2; t6 = delta.*q.*8.0; t5 = t2.*4.0; t7 = t4.*1.6e+1; t8 = t3+t5+t6+t7; t9 = sqrt(t8); t10 = t9./2.0; E1 = t4-t10+1.0; if nargout > 1 E2 = t4+t10+1.0; end end
MATLAB テスト スクリプトの実行
入力セットの固有値を計算するには、MATLAB でテスト スクリプト myTest.m
を作成して実行します。このテスト スクリプトでは、次のサイズをもつ入力を指定します。
qGrid
は128
行256
列の行列で、2 次元空間 (,) における点を表します。OmegaGrid
は128
行256
列の行列で、2 次元空間 (,) における点を表します。delta
はスカラーです。
このスクリプトでは、その後、関数 myEigenvalues.m
が呼び出されて固有値が計算されます。出力では、これらの入力値に対する固有値のプロットが表示されます。スクリプト myTest.m
の内容を以下に示します。
q = linspace(-2,2,256); Omega = linspace(0,2,128); delta = 1; [qGrid,OmegaGrid] = meshgrid(q,Omega); [E1,E2] = myEigenvalues(qGrid,OmegaGrid,delta); surf(q,Omega,E1) hold on; surf(q,Omega,E2) shading interp
MATLAB 関数からの C コードの生成
コード生成に適した MATLAB コードを作成するには、コード アナライザーとコード生成の準備状態ツールを使用します。MATLAB エディターのコード アナライザーでは、コードを入力するたびに入力したコードがチェックされます。また、問題が報告され、パフォーマンスとメンテナンス性を改善するための修正案が提示されます。コード生成の準備状態ツールでは、MATLAB コードにコード生成でサポートされていない機能や関数が含まれていないかを検査します。
コード生成に適した MATLAB コードの作成
MATLAB エディターで
myEigenvalues.m
を開きます。関数宣言の後に、%#codegen
命令を追加します。
MATLAB エディターの右上隅にあるコード アナライザーのメッセージ インジケーターは緑色です。エラー、警告、またはコード改善の余地がアナライザーによって検出されなかったためです。コード アナライザーの使い方の詳細については、コード アナライザーを使用したエラーと警告についてのコードのチェックを参照してください。
ファイルを保存します。これで、MATLAB Coder アプリを使用してコードをコンパイルできるようになりました。ここでいう "コンパイル" とは、MATLAB コードから C/C++ コードを生成することを意味します。
MATLAB Coder アプリの起動とソース ファイルの選択
MATLAB ツールストリップの [アプリ] タブの [コード生成] で、MATLAB Coder アプリのアイコンをクリックします。[ソース ファイルの選択] ページが開きます。
[ソース ファイルの選択] ページで、エントリポイント関数
myEigenvalues
の名前を入力または選択します。"エントリポイント関数" は、コードの生成元となる最上位の MATLAB 関数です。アプリは、既定の名前がmyEigenvalues.prj
のプロジェクトを現在のフォルダーに作成します。
[次へ] をクリックして [入力の型を定義] ステップに進みます。アプリが、エントリポイント関数に対し、先のステップで既に実行したコード アナライザー、およびコード生成の準備状態ツールを実行します。アプリが問題を識別すると、[コード生成の準備状態の確認] ページが開きます。ここで、問題の確認と修正を行うことができます。この例ではアプリが問題を検出していないため、[入力の型を定義] ページが開きます。詳細については、コード生成の準備状態ツール (MATLAB Coder)を参照してください。
コード アナライザーとコード生成の準備状態ツールがコード生成に関するすべての問題を検出するとは限らないことに注意してください。この 2 つのツールが検出したエラーや警告を取り除いたら、MATLAB Coder を使用してコードを生成し、コンプライアンスに関するその他の問題が MATLAB コードに存在しないかを調べます。
C/C++ コードの生成でサポートされている MATLAB の組み込み関数、ツールボックス関数、クラス、System object によっては、コード生成に関する特有の制限が存在します。これらの制限および関連する使用法については、対応する参照ページの「拡張機能」の節に記載されています。詳細については、C/C++ コードの生成でサポートされている関数およびオブジェクト (MATLAB Coder)を参照してください。
入力の型の定義
C では静的な型が使用されるため、コード ジェネレーターは、MATLAB ファイルに含まれるすべての変数のクラス、サイズ、実数/複素数をコード生成時 ("コンパイル時") に判定しなければなりません。そのため、エントリポイント関数のすべての入力のプロパティを指定しなければなりません。入力のプロパティは以下の方法で指定できます。
サンプル入力をもつエントリポイント関数を呼び出すスクリプトを与え、入力のプロパティをアプリに自動的に判定させる
プロパティを直接指定する
この例では、入力 q
、delta
および Omega
のプロパティを定義するため、テスト ファイル myTest.m
を指定してコード ジェネレーターに型を自動的に定義させます。
MATLAB プロンプトでテスト ファイル
myTest.m
を入力または選択します。[入力の型の自動定義] をクリックします。テスト ファイル
myTest.m
が、期待される入力の型をもつエントリポイント関数myEigenvalues
を呼び出します。アプリが、入力q
をdouble(128 x 256)
、入力Omega
をdouble(128 x 256)
、入力delta
をdouble(1 x 1)
と判定します。
[次へ] をクリックして [実行時の問題の確認] ステップに進みます。
実行時の問題の確認
[実行時の問題の確認] ステップでは、エントリポイント関数から MEX 関数が生成され、MEX 関数が実行され、問題が報告されます。MEX 関数は、MATLAB 内で呼び出すことができる生成コードです。生成された C コードでは診断が難しいランタイム エラーを検出して修正できるため、このステップを実行することがベスト プラクティスとなります。既定では、MEX 関数にメモリの整合性チェックが含まれています。このチェックでは、配列の範囲と次元がチェックされます。このチェックでは、MATLAB 関数に対して生成されたコードにおける、メモリの整合性違反が検出されます。詳細については、実行時チェックの制御 (MATLAB Coder)を参照してください。
コード ジェネレーターは、MATLAB コードを効率的な C/C++ ソース コードに変換するための最適化を行いますが、特定の状況においては、生成されたコードが元のソース コードと異なる動作をする場合があります。生成されたコードと MATLAB コードの相違点 (MATLAB Coder)を参照してください。
[問題の確認] の矢印
をクリックし、[実行時の問題の確認] ダイアログ ボックスを開きます (ダイアログ ボックスが自動的に開かない場合)。
[実行時の問題の確認] ダイアログ ボックスで、サンプル入力をもつエントリポイント関数を呼び出すテスト ファイルを指定するか、そのコードを入力します。この例では、入力の型の定義で使用したテスト ファイル
myTest
を使用します。[問題の確認] をクリックします。アプリが、MATLAB 内で実行する MEX 関数を生成します。このステップでは、テスト スクリプト
myTest
を実行し、myEigenvalues
への呼び出しを、生成された MEX 関数への呼び出し ([E1,E2] = myEigenvalues_mex(qGrid,OmegaGrid,delta)
) に置き換えます。生成された MEX ファイルmyEigenvalues_mex
は、work
\codegen\lib\myEigenvalues
フォルダー (Microsoft® Windows® プラットフォームの場合) またはwork
/codegen/lib/myEigenvalues
フォルダー (Linux® プラットフォームか Mac プラットフォームの場合) にあります。ここで、work
は、myEigenvalues.m
とmyTest.m
の格納場所です。MEX 関数の生成時または実行時にアプリが問題を検出した場合、警告メッセージやエラー メッセージが表示されます。これらのメッセージをクリックして問題があるコードを開き、問題を修正してください。この例では、アプリが問題を検出していません。
既定では、アプリが行の実行回数を収集します。この回数は、テスト ファイル
myTest.m
が関数myEigenvalues
をどの程度実行したかを確認するのに役立ちます。行の実行回数を表示するには、[MATLAB 行の実行回数の表示] をクリックします。アプリのエディター上で、コードの左側に色分けされたバーが表示されます。色の強調表示をコードの上まで伸ばして行の実行回数を表示するには、バーの上にカーソルを置きます。緑の網掛け表示は、固有値を計算する際にこのコードが呼び出しを 1 回しか行わないことを示しています。
[次へ] をクリックして [コード生成] ステップに進みます。
C コードの生成
[生成] の矢印
をクリックし、[生成] ダイアログ ボックスを開きます (ダイアログ ボックスが自動的に開かない場合)。
[生成] ダイアログ ボックスで、[ビルド タイプ] を
Static Library(.lib)
、[言語] を C に設定します。プロジェクトに関するその他のビルド構成設定には既定値を使用します。C スタティック ライブラリを生成する代わりに、MEX 関数またはその他の C/C++ ビルド タイプを生成するよう選択することもできます。MEX および C/C++ ビルド タイプでは、異なるプロジェクト設定を使用できます。MEX と C/C++ コードの生成を切り替える場合は、選択した設定を確認してください。
[生成] をクリックします。MATLAB Coder は、フォルダー
work
\codegen\lib\myEigenvalues
にスタンドアロンの C スタティック ライブラリmyEigenvalues
を生成します。フォルダーwork
には、myEigenvalues.m
とmyTest.m
が格納されています。コードの生成に成功すると、MATLAB Coder アプリにその旨が表示されます。ページの左側に、MATLAB のソース ファイルと生成された出力ファイルが表示されます。[変数] タブに、MATLAB ソースの変数に関する情報が表示されます。[ターゲットのビルド ログ] タブに、ビルドのログ、および C/C++ コンパイラの警告とエラーが表示されます。既定では、コード ウィンドウに C のソース コード ファイルmyEigenvalues.c
が表示されます。別のファイルを表示するには、[ソース コード] ペインまたは [出力ファイル] ペインで目的のファイル名をクリックします。
[レポートの表示] をクリックし、レポート ビューアーでレポートを表示します。コード生成時にコード ジェネレーターがエラーまたは警告を検出すると、検出された問題、および問題のある MATLAB コードへのリンクがレポートに表示されます。詳細については、コード生成レポート (MATLAB Coder)を参照してください。
[次へ] をクリックして [ワークフローの完了] ページを開きます。
[ワークフローの完了] ページの確認
[ワークフローの完了] ページには、コードの生成に成功したことを示すメッセージが表示されます。このページには、生成された出力の概要、およびその出力へのリンクが表示されます。
生成された C コードと元の MATLAB コードの比較
生成された C コードと元の MATLAB コードを比較するには、MATLAB エディターで C ファイル myEigenvalues.c
とファイル myEigenvalues.m
を開きます。
生成された C コードに関する重要な情報:
関数シグネチャーは次のようになります。
void myEigenvalues(const double q[32768], const double Omega[32768], double delta, double E1[32768], double E2[32768])
const double q[32768]
およびconst double Omega[32768]
は、MATLAB コードの入力q
およびOmega
に対応しています。q
のサイズは32768
です。これは、MATLAB コードから C/C++ コードを生成する際に使用したサンプル入力の合計サイズ(128 x 256)
に相当します。入力Omega
についても同様です。この場合、生成されたコードは、MATLAB コードの 2 次元配列を表すために 1 次元の配列を使用します。コード ジェネレーターは関数名とコメントを保持します。可能な場合、コード ジェネレーターは変数名を保持します。MATLAB コードで変数に定数値が設定されている場合、生成された C コードではその変数が現れないことに注意してください。代わりに、生成された C コードではその変数の値がリテラルとして現れます。
可変サイズの入力に対応した C コードの生成
myEigenvalues.m
について生成した C 関数は、コード生成時に指定したサンプル入力と同じサイズの入力のみを受け入れます。ただし、対応する MATLAB 関数への入力配列は、どのようなサイズにもなり得ます。例のこの部分では、myEigenvalues.m
から可変サイズの入力を受け入れる C コードを生成します。
生成された C コードに含まれる q
、Omega
、および delta
の次元に以下のプロパティを指定するとします。
q
およびdelta
の最初の次元のサイズは最大100
まで変更可能q
およびdelta
の 2 番目の次元のサイズは最大400
まで変更可能Omega
はサイズが1
行1
列のスカラー
MATLAB Coder を使用してこれらの入力のプロパティを指定するには、以下の手順を実行します。
[入力の型の定義] ステップで、前回と同じく、テスト ファイル
myTest.m
を指定して [入力の型の自動定義] をクリックします。このテスト ファイルが、期待される入力の型をもつエントリポイント関数myEigenvalues.m
を呼び出します。アプリが、入力q
をdouble(128 x 256)
、入力Omega
をdouble(128 x 256)
、入力delta
をdouble(1 x 1)
と判定します。これらの型によって、固定サイズの入力が指定されます。入力の型の指定をクリックして編集します。
:
接頭辞を使用すると、指定した値を上限とする可変サイズを指定することができます。たとえば:100
と指定すると、該当する次元のサイズを最大100
まで変更することができます。q
の型をdouble(:100 x :400)
、Omega
の型をdouble(1 x 1)
、delta
の型をdouble(:100 x :400)
に変更します。
前回と同じ手順に従ってコードを生成することができるようになります。myEigenvalues.c
で生成された C コードの関数シグネチャーは以下のようになります。
void myEigenvalues(const emxArray_real_T *q, double Omega, const emxArray_real_T *delta, emxArray_real_T *E1, emxArray_real_T *E2)
生成されたコードの引数は、元の MATLAB 関数の引数に対応しています。
emxArray_real_T*q
— 入力引数q
Omega
— 入力引数Omega
emxArray_real_T*delta
— 入力引数delta
emxArray_real_T*E1
— 出力引数E1
emxArray_real_T*E2
— 出力引数E2
これで、コンパイル時にはサイズが不明で範囲が不定の配列を表す emxArray_real_T
というデータ構造体がこの C コードに組み込まれました。詳細については、生成された関数インターフェイスでの C 配列の使用 (MATLAB Coder)を参照してください。