生成コードでの MATLAB エンジンを使用した関数呼び出しの実行
MATLAB® コードで関数 foo
の呼び出しを処理すると、コード ジェネレーターは、foo
の定義を見つけ、その本文のコードを生成します。場合によっては、コード生成をバイパスし、代わりに MATLAB エンジンを使用して呼び出しを実行できます。coder.extrinsic('foo')
を使用して、foo
の呼び出しでコードを生成するのではなく、MATLAB エンジンを実行に使用することを宣言します。このコンテキストで、foo
は外部関数として参照されます。この機能は、実行時に MATLAB エンジンが使用可能な場合にのみ使用できます。このような状況の例としては、MEX 関数の実行、Simulink® シミュレーション、またはコード生成時 ("コンパイル時" とも呼ばれる) の関数呼び出しが挙げられます。
foo
を呼び出して coder.extrinsic('foo')
を含める関数のスタンドアロン コードを生成すると、コード ジェネレーターで foo
が出力に影響するかどうか判断されます。foo
が出力に影響しない場合、コード ジェネレーターではコード生成が続行されますが、foo
は生成されたコードから除外されます。影響する場合、コンパイル エラーが発生します。
特定の MATLAB 関数内に coder.extrinsic('foo')
命令を含めると、その MATLAB 関数内での foo
の呼び出しはすべて外部関数として宣言されます。または、外部宣言のスコープを foo
の 1 回の呼び出しのみに絞り込むことができます。feval を使用した MATLAB 関数の呼び出しを参照してください。
関数を外部関数として宣言する場合
次のような場合は、MATLAB 関数を外部関数として宣言することを検討してください。
関数が表示アクションまたはログ アクションを実行する場合。このような関数は主にシミュレーション中に役立ち、組み込みのシステムでは使用されません。
MEX の実行または Simulink のシミュレーションで、コード生成についてサポートされない MATLAB 関数を使用する場合。このワークフローは、非シミュレーション ターゲットには適用されません。
coder.const
を使用して関数呼び出しを定数畳み込みするようコード ジェネレーターに指示する場合。このような場合、MATLAB エンジンで呼び出しが実行できるコード生成中にのみ関数が呼び出されます。
coder.extrinsic
コンストラクトの使用
関数 foo
を外部関数として宣言するには、MATLAB コードに次のステートメントを含めます。
coder.extrinsic('foo')
関数をコード生成の外部関数として宣言する場合は、以下のルールを守ってください。
関数を呼び出す前に外部関数として宣言する。
条件ステートメントでは外部宣言を使用しない。
外部関数の戻り値を既知の型に代入する。mxArrays の利用を参照してください。
追加情報と例については、coder.extrinsic
を参照してください。
コード ジェネレーターでは、plot
、disp
、figure
など、多くの MATLAB 可視化関数が外部関数として自動的に処理されます。coder.extrinsic
を使用してそれらを外部関数として明示的に宣言する必要はありません。たとえば、MATLAB 環境で結果を可視化するために、plot
を呼び出す場合があります。plot
を呼び出す関数から MEX 関数を生成した後、生成した MEX 関数を実行すると、コード ジェネレーターは、関数 plot
の呼び出しを MATLAB エンジンに送信します。ライブラリまたは実行可能ファイルを生成する場合、生成コードには関数 plot
への呼び出しが含まれません。
MATLAB Coder™ を使用して MEX またはスタンドアロン C/C++ コードを生成すると、コード生成レポートでは MATLAB コードから外部関数への呼び出しが強調表示されます。レポートを調べることで、MATLAB 環境でのみサポートされる関数を確認できます。
外部関数宣言のスコープ
coder.extrinsic
コンストラクトは、関数のスコープをもっています。たとえば、以下のコードについて考えます。
function y = foo %#codegen coder.extrinsic('rat','min'); [N D] = rat(pi); y = 0; y = min(N, D);
この例では、rat
と min
が、メイン関数 foo
で呼ばれるときは毎回外部関数として処理されます。メイン関数内の外部宣言のスコープを絞り込むには、以下の 2 つの方法があります。
この例のように、ローカル関数内で MATLAB 関数を外部関数として宣言します。
function y = foo %#codegen coder.extrinsic('rat'); [N D] = rat(pi); y = 0; y = mymin(N, D); function y = mymin(a,b) coder.extrinsic('min'); y = min(a,b);
ここでは、関数
rat
はメイン関数foo
内で呼び出されるときは毎回外部関数ですが、関数min
は、ローカル関数mymin
内で呼び出されるときにのみ外部関数です。coder.extrinsic
構造を使用する代わりに、feval
を使用して MATLAB 関数を呼び出します。このアプローチについては、次の節で説明します。
非静的メソッドの外部宣言
非静的メソッド foo
をもつクラス myClass
を宣言し、このクラスのインスタンス obj
を作成するとします。メソッド obj.foo
を、コード生成に使用する MATLAB コードの外部メソッドとして宣言する場合は、以下のルールに従います。
foo
の呼び出しを関数呼び出しとして記述する。ドット表記を使用して呼び出しを記述しない。構文
coder.extrinsic('foo')
を使用してfoo
を外部関数として宣言する。
たとえば、myClass
を次のように定義します。
classdef myClass properties prop = 1 end methods function y = foo(obj,x) y = obj.prop + x; end end end
foo
を外部関数として定義する MATLAB 関数の例を以下に示します。
function y = myFunction(x) %#codegen coder.extrinsic('foo'); obj = myClass; y = foo(obj,x); end
非静的メソッドは通常のメソッドとも呼ばれます。メソッドの構文を参照してください。
追加の用途
以下の処理を行う場合に coder.extrinsic
コンストラクトを使用します。
不要なコード生成を行わず、シミュレーション中に何も出力しない MATLAB 関数を呼び出す。
コードに説明コメントを付けて、デバッグしやすいようにする。ソース コードをスキャンして
coder.extrinsic
ステートメントを検出し、mxArrays
を作成して伝播させる可能性がある MATLAB 関数への呼び出しを隔離することができます。mxArrays の利用を参照してください。
feval
を使用した MATLAB 関数の呼び出し
外部宣言のスコープを 1 つの関数呼び出しのみに絞り込むには、関数 feval
を使用します。feval
は、コード生成時に自動的に外部関数として解釈されます。したがって、コンパイルしてコードを生成するよりも、feval
を使って MATLAB 環境で実行する関数を呼び出すことができます。
以下の例を考えてみます。
function y = foo coder.extrinsic('rat'); [N D] = rat(pi); y = 0; y = feval('min',N,D);
feval
は外部関数であるため、ステートメント feval('min',N,D)
は MATLAB によってコンパイルされるのではなく、評価されます。これは、この 1 回の呼び出しだけのために関数 min
を外部関数として宣言するのと同じ結果になります。それに対して、関数 rat
は、関数 foo
内で常に外部関数のままです。
コード ジェネレーターは feval
を使用したローカル関数または private フォルダー内にある関数の呼び出しをサポートしません。
mxArrays の利用
外部関数の実行時の出力は、mxArray
(別名 MATLAB 配列) です。mxArrays
に対する有効な操作は以下のみです。
mxArray
を変数に保存する。mxArray
を外部関数に渡す。関数から MATLAB に
mxArray
を返す。mxArray
を実行時に既知の型に変換する。前の代入によって型が既に定義されている変数にmxArray
を代入します。次の例を参照してください。
他の操作 (たとえば、MATLAB Function ブロックから Simulink 実行に返すなど) で外部関数から返された mxArray
を使用するには、最初にそれを既知の型に変換しなければなりません。
関数の入力引数が mxArrays
の場合、コード ジェネレーターはこの関数を自動的に外部関数として扱います。
mxArrays の既知の型への変換
mxArray
を既知の型に変換するには、mxArray
を型が定義されている変数に割り当てます。実行時に、mxArray
は代入先の変数の型に変換されます。mxArray
のデータがその変数の型と一致していない場合は、ランタイム エラーが発生します。
たとえば、以下のコードについて考えます。
function y = foo %#codegen coder.extrinsic('rat'); [N D] = rat(pi); y = min(N,D);
ここでは、最上位の関数 foo
が外部 MATLAB 関数 rat
を呼び出し、この関数が、pi
の有理分数近似の分子 N
と分母 D
を表す 2 つの mxArrays
を返します。これらの mxArrays
を別の MATLAB 関数 (この場合は min
) に渡すことができます。min
に渡される入力は mxArrays
であるため、コード ジェネレーターは自動的に min
を外部関数として扱います。その結果、min
は mxArray
を返します。
MATLAB Coder を使用して MEX 関数を生成する場合、MEX 関数はその出力を MATLAB に返すため、min
で返されたこの mxArray
を出力 y
に直接代入できます。
codegen foo
Code generation successful.
ただし、foo
を Simulink モデルの MATLAB Function ブロックに含め、モデルを更新または実行すると、次のエラーが発生します。
Code generation does not support mxArray output from this function in this context. Preinitialize output variable 'y' with a known type.
このエラーは、mxArray
を Simulink に返すことができないために発生します。この問題を修正するには、y
を、min
が返すと想定される値の型とサイズ (この場合、スカラーで double) に定義します。
function y = foo %#codegen coder.extrinsic('rat'); [N D] = rat(pi); y = 0; % Define y as a scalar of type double y = min(N,D);
この例では、外部関数 min
の出力が、コードを生成しているエントリポイント関数 foo
の出力 y
に影響を与えます。foo
のスタンドアロン コード (スタティック ライブラリなど) を生成しようとすると、コード ジェネレーターでは、外部関数呼び出しを無視できず、コード生成エラーが発生します。
codegen -config:lib foo
??? The extrinsic function 'min' is not available for standalone code generation. It must be eliminated for stand-alone code to be generated. It could not be eliminated because its outputs appear to influence the calling function. Fix this error by not using 'min' or by ensuring that its outputs are unused. Error in ==> foo Line: 4 Column: 5 Code generation failed: View Error Report Error using codegen
外部関数の使用に関する制限
コード生成時には、MATLAB の実行時環境が完全にサポートされているわけではありません。したがって、MATLAB 関数を外部呼び出しする場合には以下の制限事項が適用されます。
呼び出し元の検査や、呼び出し元のワークスペースに読み書きを行う一部の MATLAB 関数はコード生成でサポートされていません。そのような関数は以下のとおりです。
生成コード内の関数は、実行時に外部関数が以下のアクションを行う場合、予測できない結果を生じる場合があります。
フォルダーの変更
MATLAB パスの変更
MATLAB ファイルの削除または追加
警告の状態の変更
MATLAB の基本設定の変更
Simulink パラメーターの変更
コード ジェネレーターは、
coder.extrinsic
を使用した private フォルダー内の関数の呼び出しをサポートしていません。コード ジェネレーターは、
coder.extrinsic
を使用したローカル関数の呼び出しをサポートしていません。コード生成では、外部関数に渡される値または外部関数から返される値で、以下が含まれている値はサポートされません。
ハンドル クラス
関数ハンドル
不透明な値 (
coder.opaque
を参照)
外部関数の呼び出しは、入力が最大 64 個、出力が最大 64 個まで対応します。