ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

外部関数

MATLAB® コードで関数 foo の呼び出しを処理すると、コード ジェネレーターは、foo の定義を見つけ、その本文のコードを生成します。場合によっては、コード生成をバイパスし、代わりに MATLAB エンジンを使用して呼び出しを実行できます。coder.extrinsic('foo') を使用して、foo の呼び出しでコードを生成するのではなく、MATLAB エンジンを実行に使用することを宣言します。このコンテキストで、foo は外部関数として参照されます。この機能は、MATLAB エンジンが MEX 関数で使用できる場合、またはコンパイル時に coder.const を呼び出しているときにのみ使用できます。

foo を呼び出して coder.extrinsic('foo') を含める関数のスタンドアロン コードを生成すると、コード ジェネレーターで foo が出力に影響するかどうか判断されます。foo が出力に影響しない場合、コード ジェネレーターではコード生成が続行されますが、foo は生成されたコードから除外されます。影響する場合、コンパイル エラーが発生します。

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

一般的な可視化関数以外のサポートされていない関数は、外部関数として宣言しなければなりません (コード生成における関数呼び出しの解決を参照してください)。外部関数はコンパイルされず、代わりにシミュレーション中に MATLAB 内で実行されます (シミュレーション時の外部関数の解決を参照してください)。

関数を外部関数として宣言するには、以下の 2 つの方法があります。

MATLAB 関数の外部関数としての宣言

MATLAB 関数を外部関数として宣言するには、coder.extrinsic コンストラクトを main 関数またはローカル関数の先頭に追加します。

coder.extrinsic('function_name_1', ... , 'function_name_n');

外部関数の宣言

以下のコードは、MATLAB 関数 patch をローカル関数 create_plot 内で外部関数として宣言しています。axis はコード ジェネレーターで自動的に外部のものとして扱われる一般的な可視化関数の 1 つなので、axis を外部として宣言する必要はありません。

function c = pythagoras(a,b,color) %#codegen
% Calculates the hypotenuse of a right triangle
%  and displays the triangle. 

c = sqrt(a^2 + b^2);
create_plot(a, b, color);


function create_plot(a, b, color)
%Declare patch as extrinsic

coder.extrinsic('patch'); 

x = [0;a;a];
y = [0;0;b];
patch(x, y, color);
axis('equal');

コード ジェネレーターは、patchaxis のコードを生成せず、代わりに実行のためにこれらを MATLAB に送り込みます。

関数をテストするには以下の手順に従います。

  1. 次のコマンドを MATLAB プロンプトで実行し、pythagoras を MEX 関数に変換します。

    codegen -report pythagoras -args {1, 1, [.3 .3 .3]}

  2. コード生成レポートへのリンクをクリックし、レポートで create_plot の MATLAB コードを表示します。

    レポートでは関数 patch および axis が強調表示され、MATLAB 環境でのみサポートされていることが示されます。

  3. 次のコマンドを実行することでこの MEX 関数を実行します。

    pythagoras_mex(3, 4, [1.0 0.0 0.0]);

    MATLAB が、直角三角形のプロットを赤い patch オブジェクトとしてプロットします。

coder.extrinsic コンストラクトを使用する場面

以下の処理を行う場合に coder.extrinsic コンストラクトを使用します。

  • 不要なコード生成を行わず、シミュレーション中に何も出力しない MATLAB 関数を呼び出す (シミュレーション時の外部関数の解決を参照してください)。

  • コードに説明コメントを付けて、デバッグしやすいようにする。ソース コードをスキャンして coder.extrinsic ステートメントを検出し、mxArrays を作成して伝播させる可能性がある MATLAB 関数への呼び出しを隔離することができます (mxArrays の利用を参照してください)。

  • タイピングの手間が省けます。1 つの coder.extrinsic ステートメントを使えば、後に続く関数呼び出しは、呼び出しとステートメントが同じスコープ内にある限り、外部呼び出しになります (外部関数宣言のスコープを参照してください)。

  • 呼び出し関数のスコープ範囲内ではすべての MATLAB 関数を外部関数として宣言します (外部関数宣言のスコープを参照してください)。スコープを絞り込むには、feval を使います (feval を使用した MATLAB 関数の呼び出しを参照してください)。

外部関数宣言のルール

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

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

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

外部関数宣言のスコープ

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 内で呼び出されるときにのみ外部関数です。

  • feval を使用した MATLAB 関数の呼び出しに説明されているように feval を使って MATLAB 関数を呼び出します。

feval を使用した MATLAB 関数の呼び出し

関数 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 を使用したローカル関数またはプライベート フォルダー内にある関数の呼び出しをサポートしません。

非静的メソッドの外部宣言

非静的メソッド 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

非静的メソッドは通常のメソッドとも呼ばれます。メソッドと関数 (MATLAB)を参照してください。

シミュレーション時の外部関数の解決

コード ジェネレーターは外部関数 (コード生成をサポートしていない関数) への呼び出しを次のように解決します。

シミュレーション中、コード ジェネレーターは外部関数への呼び出しに対してコードを生成しますが、関数の内部コードは生成しません。したがって、シミュレーションは MATLAB ソフトウェアをインストールしたプラットフォーム上でしか実行できません。

コード生成中、コード ジェネレーターは、たとえば、mxArrays を出力変数に返すことによる影響など、外部関数を呼び出している関数の出力にその外部関数が影響を与えるかどうか判断しようとします (mxArrays の利用を参照してください)。出力に変化がない場合、コード生成は続行されますが、外部関数は生成されたコードから除外されます。それ以外の場合、コード ジェネレーターはコンパイラ エラーを発行します。

mxArrays の利用

外部関数の出力は、mxArray (別名 MATLAB 配列) です。mxArrays に対する有効な操作は以下のみです。

  • mxArrays を変数に格納する

  • mxArraysを関数に渡す、関数から返す

  • mxArrays を実行時に既知の型に変換する

他の操作で外部関数から返された mxArrays を使用するには、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 が返す mxArray を出力 y に代入することはできません。

この関数 foo を Simulink® モデルの MATLAB Function ブロックで実行すると、コードはシミュレーション中に次のエラーを発生します。

Function output 'y' cannot be of MATLAB type.

この問題を修正するには、以下に示すように、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);

コード生成時の外部関数に対する制限事項

コード生成時には、MATLAB の実行時環境が完全にサポートされているわけではありません。したがって、MATLAB 関数を外部呼び出しする場合には以下の制限事項が適用されます。

  • 呼び出し元の検査や、呼び出し元のワークスペースに読み書きを行う MATLAB 関数は、コード生成時は機能しません。そのような関数は以下のとおりです。

  • MATLAB デバッガーは、外部関数で定義されている変数を検査できません。

  • 生成コード内の関数は、実行時に外部関数が以下のアクションを行う場合、予測できない結果を生じる場合があります。

    • フォルダーの変更

    • MATLAB パスの変更

    • MATLAB ファイルの削除または追加

    • 警告の状態の変更

    • MATLAB の設定の変更

    • Simulink のパラメーターの変更

  • コード ジェネレーターは、coder.extrinsic を使用したプライベート フォルダー内の関数の呼び出しをサポートしていません。

  • コード ジェネレーターは、coder.extrinsic を使用したローカル関数の呼び出しをサポートしていません。

関数の引数に対する制限事項

関数の呼び出しは、入力が最大 64 個、出力が最大 64 個まで対応します。