Main Content

生成コードでの 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 関数の呼び出しを参照してください。

This image shows the flowchart on what you should do when using the MATLAB engine to execute the call to a function.

関数を外部関数として宣言する場合

次のような場合は、MATLAB 関数を外部関数として宣言することを検討してください。

  • 関数が表示アクションまたはログ アクションを実行する場合。このような関数は主にシミュレーション中に役立ち、組み込みのシステムでは使用されません。

  • MEX の実行または Simulink のシミュレーションで、コード生成についてサポートされない MATLAB 関数を使用する場合。このワークフローは、非シミュレーション ターゲットには適用されません。

  • coder.const を使用して関数呼び出しを定数畳み込みするようコード ジェネレーターに指示する場合。このような場合、MATLAB エンジンで呼び出しが実行できるコード生成中にのみ関数が呼び出されます。

coder.extrinsic コンストラクトの使用

関数 foo を外部関数として宣言するには、MATLAB コードに次のステートメントを含めます。

coder.extrinsic('foo')

関数をコード生成の外部関数として宣言する場合は、以下のルールを守ってください。

  • 関数を呼び出す前に外部関数として宣言する。

  • 条件ステートメントでは外部宣言を使用しない。

  • 外部関数の戻り値を既知の型に代入する。mxArrays の利用を参照してください。

追加情報と例については、coder.extrinsic を参照してください。

コード ジェネレーターでは、plotdispfigure など、多くの MATLAB 可視化関数が外部関数として自動的に処理されます。coder.extrinsic を使用してそれらを外部関数として明示的に宣言する必要はありません。たとえば、MATLAB 環境で結果を可視化するために、plot を呼び出す場合があります。plot を呼び出す関数から MEX 関数を生成した後、生成した MEX 関数を実行すると、コード ジェネレーターは、関数 plot の呼び出しを MATLAB エンジンに送信します。ライブラリまたは実行可能ファイルを生成する場合、生成コードには関数 plot への呼び出しが含まれません。

MATLAB Coder™ を使用して MEX またはスタンドアロン C/C++ コードを生成すると、コード生成レポートでは MATLAB コードから外部関数への呼び出しが強調表示されます。レポートを調べることで、MATLAB 環境でのみサポートされる関数を確認できます。

This image shows the report for the function mystats. The cursor points to the extrinsic function, plot, and the report displays the function properties. The extrinsic function is purple.

外部関数宣言のスコープ

coder.extrinsic コンストラクトは、関数のスコープをもっています。たとえば、以下のコードについて考えます。

function y = foo %#codegen
coder.extrinsic('rat','min');
[N D] = rat(pi);
y = 0;
y = min(N, D);

この例では、ratmin が、メイン関数 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 を外部関数として扱います。その結果、minmxArray を返します。

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 個まで対応します。

参考

|