Main Content

coder.extrinsic

外部として関数を宣言し MATLAB で実行

説明

coder.extrinsic(function)function を外部関数として宣言します。コード ジェネレーターは外部関数の本体のコードを生成せず、代わりに MATLAB® エンジンを使用して呼び出しを実行します。この機能は、実行時に MATLAB エンジンが使用可能な場合にのみ使用できます。MATLAB エンジンが使用可能な状況の例としては、MEX 関数の実行、Simulink® シミュレーション、またはコード生成時 (コンパイル時とも呼ばれる) の関数呼び出しが挙げられます。

スタンドアロン コードの生成中に、コード ジェネレーターは外部関数に副作用のみがあるかどうか (たとえば、プロットを表示することによって)、または呼び出し元の関数の出力に影響を与えるかどうか (たとえば、出力変数に値を返すことによって) を判断しようとします。出力に変化がない場合、コード ジェネレーターはコード生成を進めますが、生成コードから外部関数を除外します。影響する場合、コンパイル エラーが発生します。

coder.extrinsic を使用して外部関数として宣言した関数では、coder.ceval を使用することはできません。また、コード生成の範囲外では、coder.extrinsic 命令は無視されます。

生成コードでの MATLAB エンジンを使用した関数呼び出しの実行を参照してください。

メモ

コード ジェネレーターでは、plotdispfigure など、多くの MATLAB 可視化関数が外部関数として自動的に処理されます。coder.extrinsic を使用してそれらを外部関数として明示的に宣言する必要はありません。

coder.extrinsic(function1, ... ,functionN)function1 から functionN まで外部関数として宣言します。

coder.extrinsic('-sync:on', function1, ... ,functionN) は、外部関数 function1 から functionN までの呼び出しの前後で、MATLAB 実行と生成されたコードの実行または Simulink シミュレーションとの間のグローバル データの同期を有効にします。少数の外部呼び出しのみがグローバル データを使用または変更する場合、グローバル同期モードを At MEX-function entry and exit に設定してすべての外部関数呼び出しの前後で同期を無効にします。グローバル データを修正する外部呼び出しに対してのみ、'-sync:on' オプションを使用して同期を有効にします。

MATLAB Coder™ を使用して MEX 関数を生成する場合、'-sync:on' オプションを使用すると、定数のグローバル データに対しては、外部関数の呼び出し後に MATLAB 関数と MEX 関数との整合性の検証が有効になります。

グローバル データのためのコード生成 (MATLAB Coder)を参照してください。

coder.extrinsic('-sync:off', function1, ... ,functionN) は、外部関数 function1 から functionN までの呼び出しの前後で、MATLAB 実行と生成されたコード実行との間のグローバル データの同期を無効にします。少数の外部呼び出しを除き、ほとんどの外部呼び出しでグローバル データを使用または修正する場合、グローバル データを修正しない外部呼び出しに対しては、'-sync:off' オプションを使用して同期を無効にします。

MATLAB Coder を使用して MEX 関数を生成する場合、'-sync:off' オプションを使用すると、定数のグローバル データに対しては、外部関数の呼び出し後に MATLAB 関数と MEX 関数との整合性の検証が無効になります。

グローバル データのためのコード生成 (MATLAB Coder)を参照してください。

すべて折りたたむ

MATLAB 関数 str2num はコード生成でサポートされていません。この例は、MATLAB の関数で str2num を外部関数として宣言することにより、生成された MEX 関数で str2num の機能を引き続き使用する方法を説明します。

この MATLAB コードは str2num をローカル関数 convertStringToNumber の外部関数として宣言します。str2num を外部関数として宣言することにより、str2num のコード生成を行わないようコード ジェネレーターに指示します。代わりに、コード ジェネレーターは str2num を実行のために MATLAB に送ります。

function n = convertStringToNumber(c)
    %#codegen
    coder.extrinsic('str2num');
    n = str2num(c);
end

convertStringToNumber の MEX 関数を生成します。

codegen convertStringToNumber -args {coder.typeof('c', [1 Inf])} -report

レポートで生成コードを確認できます。

/* Function Definitions */
static const mxArray *str2num(const emlrtStack *sp, 
                const mxArray *m1,emlrtMCInfo *location)
{
  const mxArray *m;
  const mxArray *pArray;
  pArray = m1;
  return emlrtCallMATLABR2012b((emlrtConstCTX)sp, 1, &m, 1, 
                          &pArray, "str2num", true, location);
}

外部関数が実行時に返す出力は、mxArray (別名 MATLAB 配列) です。mxArray に対する有効な操作は、変数に保存すること、別の外部関数に渡すこと、MATLAB に返すことだけです。コードの式で使用するなど、mxArray 値に対して他の操作を実行するには、実行時に mxArray を既知の型に変換する必要があります。このアクションを実行するには、前の代入によって型が既に定義されている変数に mxArray を代入します。

この例では、mxArray 出力を外部関数から MATLAB に直接返す方法を示します。次の例では、同じ mxArray 出力を既知の型に変更してから、それを MATLAB 関数内の式で使用する方法を示します。

エントリポイント関数の定義

関数 hascycles を使用して、有向グラフのソース ノードのインデックスとターゲット ノードのインデックスを入力として受け入れ、グラフが非循環であるかどうかを判定する MATLAB 関数 return_extrinsic_output を定義します。関数 hascycles はコード生成でサポートされておらず、外部関数として宣言されます。

type return_extrinsic_output.m
function hasCycles = return_extrinsic_output(source,target)
coder.extrinsic('hascycles');
assert(numel(source) == numel(target))
G = digraph(source,target);
hasCycles = hascycles(G);
end

MEX 関数の生成と呼び出し

return_extrinsic_output の MEX コードを生成します。入力を double 型の非有界のベクトルであると指定します。

codegen return_extrinsic_output -args {coder.typeof(0,[1 Inf]),coder.typeof(0,[1 Inf])} -report
Code generation successful: To view the report, open('codegen/mex/return_extrinsic_output/html/report.mldatx')

適切な入力を使用して、生成された MEX 関数 return_extrinsic_output_mex を呼び出します。

return_extrinsic_output([1 2 4 4],[2 3 3 1])
ans = logical
   0

有向グラフに循環があるかどうかを視覚的に検査するには、MATLAB で有向グラフをプロットします。

plot(digraph([1 2 4 4],[2 3 3 1]))

Figure contains an axes object. The axes object contains an object of type graphplot.

外部関数が返す出力は、mxArray (別名 MATLAB 配列) です。mxArray に対する有効な操作は、変数に保存すること、別の外部関数に渡すこと、MATLAB に返すことだけです。コードの式で使用するなど、mxArray 値に対して他の操作を実行するには、実行時に mxArray を既知の型に変換します。このアクションを実行するには、前の代入によって型が既に定義されている変数に mxArray を代入します。

次の例では、外部関数の mxArray 出力を既知の型に変更してから、出力を MATLAB 関数内の式で使用する方法を示します。

エントリポイント関数の定義

関数 hascycles を使用して、有向グラフのソース ノードのインデックスとターゲット ノードのインデックスを入力として受け入れ、グラフが非循環であるかどうかを判定する MATLAB 関数 use_extrinsic_output を定義します。関数 hascycles はコード生成でサポートされておらず、外部関数として宣言されます。エントリポイント関数には関数 hascycles の出力に基づいたメッセージが表示されます。

type use_extrinsic_output
function use_extrinsic_output(source,target) %#codegen
assert(numel(source) == numel(target))
G = digraph(source,target);

coder.extrinsic('hascycles');
hasCycles = true;

hasCycles = hascycles(G);
if hasCycles == true
    disp('The graph has cycles')
else
    disp('The graph does not have cycles')
end
end

ローカル変数 hasCycles は、代入 hasCycles = hascycles(G) が行われる前の最初の既定のブール値 true です。この既定により、コード ジェネレーターは外部関数 hascycles が返す mxArray をブール値に変換してから変数 hasCycles に代入できます。それに対し、この変換により、if ステートメントの条件で hasCycles をブール true と比較できます。

MEX 関数の生成と呼び出し

use_extrinsic_output の MEX コードを生成します。入力を double 型の非有界のベクトルであると指定します。

codegen use_extrinsic_output -args {coder.typeof(0,[1 Inf]),coder.typeof(0,[1 Inf])} -report
Code generation successful: To view the report, open('codegen/mex/use_extrinsic_output/html/report.mldatx')

適切な入力を使用して、生成された MEX 関数 use_extrinsic_output_mex を呼び出します。

use_extrinsic_output_mex([1 2 4 4],[2 3 3 1])
The graph does not have cycles

有向グラフに循環があるかどうかを確認するには、MATLAB でグラフをプロットします。

plot(digraph([1 2 4 4],[2 3 3 1]))

Figure contains an axes object. The axes object contains an object of type graphplot.

この例では、coder.constを使用してコード生成時 (コンパイル時とも呼ばれる) に外部関数を呼び出す方法を示します。MATLAB エンジンは coder.const 内の式の評価中に常に使用できるため、MEX またはスタンドアロン コードのいずれかを生成する際にこのコーディング パターンを使用できます。ランタイム実行を示す前の 2 つの例とは違い、評価がコンパイル時に行われる場合は、外部関数の出力を既知の型に明示的に変換する必要はありません。

この例では、エントリポイント関数 rotate_complex は XML 処理の MATLAB API を使用する別の関数 xml2struct を呼び出します。コード生成では XML 処理用の MATLAB API がサポートされないため、関数 xml2struct はエントリポイント関数の本文で外部として宣言されます。また、エントリポイント関数内での xml2struct の呼び出しは、コンパイル時の定数を返します。このため、関数呼び出しを coder.const 命令内に配置することにより、この出力では定数が畳み込まれます。

パラメーターを含む XML ファイルの検査

サポート ファイル complex.xml には複素数の実数部と虚数部の値が含まれます。

type complex.xml
<params>
    <param name="real" value="3"/>
    <param name="imaginary" value="4"/>
</params>

関数 xml2struct の定義

MATLAB 関数 xml2structcomplex.xml の形式を使用してパラメーター名と値を保存する XML ファイルを読み取り、この情報を構造体フィールドとして保存して、次の構造体を返します。

type xml2struct.m
function s = xml2struct(file)
s = struct();
import matlab.io.xml.dom.*
doc = parseFile(Parser,file);
els = doc.getElementsByTagName("params");
for i = 0:els.getLength-1
    it = els.item(i);
    ps = it.getElementsByTagName("param");
    for j = 0:ps.getLength-1
        param = ps.item(j);
        paramName = char(param.getAttribute("name"));
        paramValue = char(param.getAttribute("value"));
        paramValue = evalin("base", paramValue);
        s.(paramName) = paramValue;
    end
end

エントリポイント関数の定義

MATLAB エントリポイント関数 rotate_complex は最初に xml2struct を呼び出してファイル complex.xml を読み取ります。次に、入力引数 theta と等しい角度 (度単位) で複素数を回転し、その結果得られる複素数を返します。

type rotate_complex.m
function y = rotate_complex(theta) %#codegen
coder.extrinsic("xml2struct");
s = coder.const(xml2struct("complex.xml"));

comp = s.real + 1i * s.imaginary;
magnitude = abs(comp);
phase = angle(comp) + deg2rad(theta);
y = magnitude * cos(phase) + 1i * sin(phase);

end

関数 xml2struct は外部として宣言され、関数を coder.const 命令内に配置することにより、その出力では定数が畳み込まれます。

スタティック ライブラリの生成と検査

codegen (MATLAB Coder)コマンドを使用して read_complex のスタティック ライブラリを生成します。入力の型を double 型のスカラーに指定します。

codegen -config:lib rotate_complex -args {0} -report 
Warning: Code generation is using a coder.EmbeddedCodeConfig object. Because
Embedded Coder is not installed, this might cause some Embedded Coder features
to fail.

Code generation successful (with warnings): To view the report, open('codegen/lib/rotate_complex/html/report.mldatx')

生成された C++ ファイル rotate_complex.c を検査します。関数 xml2struct の出力が生成されたコードでハードコードされることを観察します。

type codegen/lib/rotate_complex/rotate_complex.c
/*
 * File: rotate_complex.c
 *
 * MATLAB Coder version            : 5.6
 * C/C++ source code generated on  : 19-Feb-2023 12:23:29
 */

/* Include Files */
#include "rotate_complex.h"
#include <math.h>

/* Function Definitions */
/*
 * Arguments    : double theta
 * Return Type  : creal_T
 */
creal_T rotate_complex(double theta)
{
  creal_T y;
  double y_tmp;
  y_tmp = 0.017453292519943295 * theta + 0.92729521800161219;
  y.re = 5.0 * cos(y_tmp);
  y.im = sin(y_tmp);
  return y;
}

/*
 * File trailer for rotate_complex.c
 *
 * [EOF]
 */

入力引数

すべて折りたたむ

外部関数として宣言される MATLAB 関数の名前。

例: coder.extrinsic('patch')

データ型: char

制限

  • 外部関数呼び出しには、パフォーマンスに影響する可能性のある何らかのオーバーヘッドがあります。外部関数呼び出しで渡される入力データは MATLAB に指定しなければなりません。これにはデータのコピー作成が必要になります。関数に出力データが含まれている場合、このデータは MEX 関数環境に再転送しなければなりません。これにもコピーが必要になります。

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

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

ヒント

  • コード ジェネレーターでは、plotdispfigure など、多くの MATLAB 可視化関数が外部関数として自動的に処理されます。coder.extrinsic を使用してそれらを外部関数として明示的に宣言する必要はありません。

  • 外部関数として宣言しなければならない関数を検出するには、関数 coder.screener を使用します。この関数は、MATLAB コード内にコード生成でサポートされない機能や関数がないかどうかを調べるコード生成の準備状態ツールを実行します。

拡張機能

C/C++ コード生成
MATLAB® Coder™ を使用して C および C++ コードを生成します。

GPU コード生成
GPU Coder™ を使用して NVIDIA® GPU のための CUDA® コードを生成します。

バージョン履歴

R2011a で導入