Main Content

クラス インターフェイスをもつ C++ コードの生成

C コードを生成する場合、ソフトウェアは MATLAB® コードを解析して、エントリポイント MATLAB 関数に対応するエントリポイント C 関数を生成します。C++ コードを生成する場合、C++ クラスのメソッドとしてエントリポイント関数を生成するよう選択することができます。このオプションを使用すると次のようになります。

  • よりオブジェクト指向のコードが得られる。

  • コード ジェネレーターは、メモリの初期化と終了を自動的に実行するクラス コンストラクターとクラス デストラクターを作成する。

  • それぞれのクラス インスタンスに個別にメモリを割り当てる。各クラス インスタンスのメソッドはスレッドセーフで再呼び出し可能である。

  • 複数のエントリポイント関数が単一の C++ クラスのメソッドになる。

コマンド ラインから、または MATLAB Coder™ アプリから、クラス インターフェイスをもつコードを生成できます。コマンド ラインからは、CppInterfaceStyle 構成パラメーターおよび CppInterfaceClassName 構成パラメーターを使用します。アプリからは、[コード生成] のステップで [言語][C++] を、[インターフェイス スタイル][メソッド] を選択し、[C++ インターフェイス クラス名] を指定します。

これらの例ではコマンド ラインのワークフローを説明します。

クラス インターフェイスをもつ C++ コードの生成

この例では、生成された C++ コードがクラス インターフェイスを使用する場合の相違点を説明します。

MATLAB アルゴリズム

行列に対する演算を行い結果を出力する単純な MATLAB 関数について考えます。

function out = foog %#codegen
I = eye(447);
out = ones(447)*I + 7;

クラス インターフェイスをもつ C++ コードとクラス インターフェイスをもたない C++ コードの生成

クラス インターフェイスをもつ C++ コードを生成するには、CppInterfaceStyle パラメーターと CppInterfaceClassName パラメーターを使用します。出力を withClass フォルダーに格納します。

cfg = coder.config('lib');
cfg.GenCodeOnly = true;
cfg.TargetLang = 'C++';
cfg.CppInterfaceStyle = 'Methods';
cfg.CppInterfaceClassName = 'myClass';
codegen foog -config cfg -report -d withClass
Code generation successful: To view the report, open('withClass/html/report.mldatx')

次に、新しい構成オブジェクトを作成し、クラス インターフェイスを使用しない C++ コードを生成します。

cfg = coder.config('lib');
cfg.GenCodeOnly = true;
cfg.TargetLang = "C++";
codegen foog -config cfg -report -d withoutClass
Code generation successful: To view the report, open('withoutClass/html/report.mldatx')

生成された main 関数の例を調べます。クラス インターフェイスをもつバージョンと、もたないバージョンを比較します。クラス インターフェイスがある場合、main 関数はエントリポイント関数をクラス メソッドとして呼び出します。

type withClass/examples/main.cpp

生成されたコードでのクラス定義と実装

コード ジェネレーターが C++ インターフェイス クラス向けのコードを生成すると、関数メソッドが再呼び出し可能であることが確保されます。関数メソッドが構成パラメーター StackUsageMax で設定されるローカル スタック メモリの制限を超える可能性のある変数を使用する場合、コード ジェネレーターは変数 (接尾辞 StackData で識別可能) に対してプライベートなデータ構造体を作成します。変数を static として宣言することはありません。静的変数は複数の関数の呼び出し間で保持され、再呼び出し可能となりません。再呼び出し可能な C コードの生成の詳細については、再呼び出し可能なコードの生成と呼び出しを参照してください。

生成されたクラス実装を調べるには、関数 foog を、構成パラメーター StackUsageMax で指定された最大スタック使用量を超える変数を含むように変更します。

function out = foogBig %#codegen
I = eye(448);
out = ones(448)*I + 7;

StackUsageMax の既定値 (バイト) は次のようになります。

cfg.StackUsageMax
ans =

  int32

   200000

fooBig が 448^2 (200704) 個の要素の変数を使用し、かつコード ジェネレーターが 8 ビットの整数の配列を作成して変数を表すため、既定のスタック使用量制限を 704 バイト超過します。foogBig のコードを生成します。

cfg = coder.config('lib','ecoder',false);
cfg.GenCodeOnly = true;
cfg.TargetLang = 'C++';
cfg.CppInterfaceStyle = 'Methods';
cfg.CppInterfaceClassName = 'myBigClass';
codegen foogBig -config cfg -report -d withBigClass
Code generation successful: To view the report, open('withBigClass/html/report.mldatx')

生成されたインターフェイス クラス定義の検証

foogBig プロジェクトのクラス定義、および foog のクラス定義を検証します。foogBig クラスは最大スタック使用量を超過する可能性のある変数をプライベートなクラス プロパティに格納しますが、foog クラスはスタックにローカル変数を作成するだけです。

このクラスがローカル スタックの使用量制限を超過するデータを必要とすることを示す StackData 構造体を含むクラス定義について作業する場合、new を使用してクラス インスタンスにヒープ メモリを割り当てます。例については、生成されたコードの生成された main ファイルの例を参照してください。

生成された C++ クラスのグローバルと永続

クラス インターフェイスをもつ C++ を生成する場合、クラスのメンバーとしてグローバルと永続にアクセスします。この例では、クラスのグローバルと永続について作業する方法を示します。

MATLAB アルゴリズム

グローバル変数と永続変数を使用して呼び出した回数のカウントを保持する MATLAB 関数について考えます。

function [po,go] = countCalls %#codegen
% increment persistent & global variable
persistent p
global g
if isempty(p)
    p = 0;
end
p = p+1;
g = g+1;
% set output variables 
po = double(p);
go = double(g);

クラス インターフェイスをもつ C++ コードの生成

コード生成のため、ワークスペースのグローバル変数を初期化します。

global g;
g = 0;

countClass というクラスでコードを生成します。

cfg = coder.config('lib');
cfg.GenCodeOnly = true;
cfg.TargetLang = 'C++';
cfg.CppInterfaceStyle = 'Methods';
cfg.CppInterfaceClassName = "countClass";
codegen countCalls -config cfg -report
Code generation successful: To view the report, open('codegen/lib/countCalls/html/report.mldatx')

クラス定義の検証

生成された C++ コードで、初期化関数がグローバル変数をワークスペースで指定する値に設定します。グローバル変数の初期値は codegen -globals 構文で指定することもできます。

コードをヘッダー ファイル countClass.h のクラス定義について検証します。

type codegen/lib/countCalls/countClass.h

グローバル変数はクラスのパブリック メンバーです。必要に応じて main 関数からこの変数にアクセスします。永続変数はプライベートなクラス データ構造体に格納されます。

複数のエントリポイント関数の同一クラスへの配置

複数のエントリポイント関数の C++ コードを生成してクラス インターフェイス設定を使用すると、各関数が同じクラスのパブリック メソッドになります。この手法を使用して、複数のエントリポイント関数プロジェクトに、より単純なインターフェイスを作成できます。

MATLAB エントリポイント関数

前の例の関数 countCalls を 2 つに分割して、1 つの関数が永続変数を使用して呼び出しをカウントし、もう 1 つの関数がグローバル変数を使用して呼び出しをカウントするようにします。2 つの関数を検証します。

function po = countPersistent %#codegen
% increment persistent variable
persistent p
if isempty(p)
    p = 0;
end
p = p+1;
% set output variable
po = double(p);

function go = countGlobal %#codegen
% increment global variable
global g
g = g+1;
% set output variable
go = double(g);

C++ コードの生成

codegen コマンドを使用して、グローバル変数の初期値を入力として指定します。

cfg = coder.config('lib');
cfg.GenCodeOnly = true;
cfg.TargetLang = 'C++';
cfg.CppInterfaceStyle = 'Methods';
cfg.CppInterfaceClassName = 'countClassMulti';
codegen countGlobal countPersistent -config cfg -report -globals {'g',0}
Code generation successful: To view the report, open('codegen/lib/countGlobal/html/report.mldatx')

生成されたコードの確認

生成されたクラス定義を確認するには countClassMulti.h を開きます。各エントリポイント関数はクラスのパブリック メソッドです。

type codegen/lib/countGlobal/countClassMulti.h

参考

関連するトピック