生成された関数インターフェイスでの動的に割り当てられた C++ 配列の使用
ほとんどの場合、配列を受け入れるか配列を返す MATLAB® 関数のコードを生成すると、生成された C/C++ 関数のインターフェイスに配列が含まれます。コンパイル時にサイズが不明な配列、または事前定義されたしきい値を制限が超える配列の場合、生成された配列のメモリはヒープで動的に割り当てられます。それ以外の場合、生成された配列のメモリはスタックで静的に割り当てられます。可変サイズの配列に対するメモリ割り当ての制御を参照してください。
コード生成のターゲット言語として C++ を選択した場合、既定では、動的に割り当てられた配列は生成されたコードに coder::array
というクラス テンプレートとして実装されます。動的に割り当てられた配列を生成された C++ 関数と統合するカスタム C++ コードで使用するには、coder::array
テンプレートの使用方法を習得してください。
coder::array
クラス テンプレートの使用
MATLAB 関数の C++ コードを生成すると、コード ジェネレーターによってビルド フォルダーにヘッダー ファイル coder_array.h
が生成されます。このヘッダー ファイルには、名前空間 coder
内のクラス テンプレート array
の定義が含まれています。coder::array
テンプレートは、生成されたコードに動的に割り当てられた配列を実装します。このテンプレートの宣言は次のとおりです。
template <typename T, int32_T N> class array
T
型の要素が含まれ、その次元数は N
です。たとえば、カスタム C++ コードで int32_T
型の要素を含む 2 次元の動的な配列 myArray
を宣言するには、次を使用します。coder::array<int32_T, 2> myArray
動的に割り当てられた配列を生成されたコード (カスタム main 関数など) と統合するカスタム C++ コードで使用するには、coder_array.h
ヘッダー ファイルをカスタム .cpp
ファイルに含めます。次の表に、カスタム C++ コードで動的な配列を作成して操作するために使用する API を示します。
アクション | 手順 |
---|---|
|
coder::array<int32_T, 2> myArray |
|
myArray.set_size(1, 100)
|
|
myArray.size(1) |
動的な配列 | 配列インデックス付けの標準の C++ 構文を使用します。たとえば、 myArray[i] = i また、標準の C++ 構文を使用して多次元配列にインデックスを付けるか、 myArray[i][j] = i*j; // You can also use the 'at' function myArray.at(i,j) = i * j; |
変数 | コピー コンストラクターを使用して、配列 std::vector<int32_T> vec; // Create coder::array copy coder::array<int32, 2> copyArray(vec);
|
例
次の例では、可変サイズの数値配列と文字配列を受け入れて返す C++ コードの生成方法を説明します。動的に割り当てられた配列をカスタム C++ コードで使用するには、coder_array.h
ヘッダー ファイルをカスタム .cpp
ファイルに含めます。coder::array
クラス テンプレートには、配列メモリの割り当てと解放を実行できるメソッドがあります。
動的サイズの配列である std::vector
または std::string
の配列と生成コード間のインターフェイスを取ることもできます。これらの配列は、生成された関数への入力としても使用できます。可変サイズの文字ベクトルを受け入れて返す C++ コードの生成を参照してください。
可変サイズの数値配列を受け入れて返す C++ コードの生成
この例では、プロジェクトの coder::array
クラス テンプレートを使用するように、生成された main 関数の例をカスタマイズする方法を示します。関連するメソッドについては、上記の表を参照してください。
目的は、int32_T
要素の配列を受け入れて返すことができる xTest1
の C++ 実行可能ファイルを生成することです。配列の最初の次元の大きさを 1 にして、2 番目の次元を制限なしにするとします。
配列
X
を受け入れてその各要素にスカラーA
を追加し、結果の配列Y
を返す MATLAB 関数xTest1
を定義します。function Y = xTest1(X, A) Y = X; for i = 1:numel(X) Y(i) = X(i) + A; end
xTest1
の初期ソース コードを生成します。次のコマンドを使用します。cfg = coder.config('lib'); cfg.TargetLang = 'C++'; codegen -config cfg -args { coder.typeof(int32(0), [1 inf]), int32(0)} xTest1.m -report
生成されたコード内の
xTest1
の関数プロトタイプは次のとおりです。void xTest1(const coder::array<int, 2U> &X, int A, coder::array<int, 2U> &Y)
上記の関数プロトタイプと互換性のある入力配列と出力配列を指定して、生成コードとのインターフェイスを取ります。
現在の作業フォルダー内のファイル
xTest1_main.cpp
で C++ main 関数を定義します。この main 関数には、
coder::array
クラス テンプレートの定義を含むヘッダー ファイルcoder_array.h
が含まれています。この main 関数は、前の節の表で説明した API を使用して次のアクションを実行します。myArray
とmyResult
をint32_T
要素の 2 次元の動的な配列として宣言する。set_size
メソッドを使用して、myArray
の 2 つの次元のサイズを1
と100
に動的に設定する。myResult.size
を使用して、myResult
のサイズ ベクトルにアクセスする。
#include<iostream> #include<coder_array.h> #include"xTest1.h" int main(int argc, char *argv[]) { static_cast<void>(argc); static_cast<void>(argv); // Instantiate the input variable by using coder::array template coder::array<int32_T, 2> myArray; // Allocate initial memory for the array myArray.set_size(1, 100); // Access array with standard C++ indexing for (int i = 0; i < myArray.size(1); i++) { myArray[i] = i; } // Instantiate the result variable by using coder::array template coder::array<int32_T, 2> myResult; // Pass the input and result arrays to the generated function xTest1(myArray, 1000, myResult); for (int i = 0; i < myResult.size(1); i++) { if (i > 0) std::cout << " "; std::cout << myResult[i]; if (((i+1) % 10) == 0) std::cout << std::endl; } std::cout << std::endl; return 0; }
次のスクリプトを実行してコードを生成します。
cfg = coder.config('exe'); cfg.TargetLang = 'C++'; cfg.CustomSource = 'xTest1_main.cpp'; cfg.CustomInclude = '.'; %current working directory codegen -config cfg -args { coder.typeof(int32(0), [1 inf]), int32(0)} xTest1_main.cpp xTest1.m -report
コード ジェネレーターによって現在の作業フォルダーに実行可能ファイル xTest1.exe
が生成されます。
可変サイズの文字ベクトルを受け入れて返す C++ コードの生成
この例では、coder::array
クラス メソッドを使用して string 配列と生成コード間のインターフェイスを取るように、生成されたメイン ファイルの例をカスタマイズする方法を示します。
この例の main 関数は std::vector
を使用して、生成された C++ 関数 xStringTest
に渡す char_T
要素のベクトル vec
を宣言します。
文字ベクトル
str
を受け入れて文字ベクトル'hello '
と' world!'
の間にstr
を挿入し、結果を返す MATLAB 関数xStringTest
を定義します。目的は、xStringTest
から C++ 実行可能ファイルを生成することです。function y = xStringTest(str) assert(isa(str, 'char')); assert(size(str,1) == 1); assert(size(str,2) >= 0); y = ['hello ' str ' world!'];
xStringTest
のソース コードを生成します。次のコマンドを使用します。cfg = coder.config('lib'); cfg.TargetLang = 'C++'; codegen -config cfg -args {coder.typeof(char('X'), [1 inf])} xStringTest.m -report
レポートで、生成されたコード内の
xStringTest
の関数プロトタイプを確認します。void xStringTest(const coder::array<char, 2U> &str, coder::array<char, 2U> &y)
上記の関数プロトタイプと互換性のある入力配列と出力配列を指定して、生成コードとのインターフェイスを取ります。
現在の作業フォルダー内のファイル
xStringTest_main.cpp
で C++ main 関数を定義します。この main 関数では、入力配列を
char_T
の配列std::vector
として定義します。for
ループは、文字値をもつvec
を'A'
から'J'
に初期化します。この配列は、xStringTest
の生成された関数への入力です。関数の出力は、coder::array
の変数result
に返されます。#include<iostream> #include<coder_array.h> #include<xStringTest.h> int main(int, char *[]) { // Instantiate the result variable by using coder::array template coder::array<char_T, 2> result; // Instantiate the input variable by using std::vector std::string vec; // Resize the input to include required values vec.resize(10); vec = "ABCDEFGHIJ"; // Pass the input and result arrays to the generated function interface xStringTest(vec, result); //Cast coder::array 'result' variable to std::string to display it std::cout << "Result is "; std::cout << static_cast<std::string>(result) << std::endl; return 0; }
次のスクリプトを実行してコードを生成します。
cfg = coder.config('exe'); cfg.TargetLang = 'C++'; cfg.CustomSource = 'xStringTest_main.cpp'; cfg.CustomInclude = '.'; %current working directory codegen -config cfg -args {coder.typeof(char('X'), [1 inf])} xStringTest_main.cpp xStringTest.m -report
コード ジェネレーターによって現在の作業フォルダーに実行可能ファイル xStringTest.exe
が生成されます。
N 次元配列を受け入れて返す C++ コードの生成
目的は、int32_T
要素の N 次元配列を受け入れて返すことができる xTest2
の C++ 実行可能ファイルを生成することです。
3 次元配列
X
を受け入れてその各要素からスカラーA
を減算し、結果の配列をY
で返す関数xTest2
を定義します。function Y = xTest2(X,A) Y = X; for i = 1:size(X,1) for j = 1:size(X,2) for k = 1:size(X,3) Y(i,j,k) = X(i,j,k) - A; end end end end
xTest2
の初期ソース コードを生成します。次のコマンドを使用します。cfg = coder.config('lib'); cfg.TargetLang = 'C++'; codegen -config cfg -args {coder.typeof(0,[inf inf inf]),0} xTest2.m -report
生成されたコード内の
xTest2
の関数プロトタイプは次のとおりです。xTest2(const coder::array<double, 3U> &X, double A,... coder::array<double, 3U> &Y);
上記の関数プロトタイプと互換性のある入力配列と出力配列を指定して、生成コードとのインターフェイスを取ります。
現在の作業フォルダー内のファイル
xTest2_main.cpp
で C++ main 関数を定義します。この main 関数には、
coder::array
クラス テンプレートの定義を含むヘッダー ファイルcoder_array.h
が含まれています。この main 関数は、前の節の表で説明した API を使用して次のアクションを実行します。生成された関数への入力および出力として 2 つの 3 次元配列
myArray
およびmyResult
を宣言する。set_size
メソッドを使用して、myArray
の次元のサイズを4
に設定する。myResult.size
を使用して、myResult
のサイズ ベクトルにアクセスする。
#include<iostream> #include<coder_array.h> #include"xTest2.h" int main() { // Instantiate the input variable by using coder::array template coder::array<double, 3U> myArray; // Allocate initial memory for the array myArray.set_size(4, 4, 4); // Access array with standard C++ indexing for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++){ for (int k = 0; k < 4; k++) { myArray.at(i,j,k) = i * j * k; } } } // Instantiate the result variable by using coder::array template coder::array<double, 3U> myResult; // Pass the input and result arrays to the generated function xTest2(myArray, 1, myResult); for (int i = 0; i < myResult.size(1); i++) { if (i > 0) std::cout << " "; for (int j = 0; j < 4; j++){ for (int k = 0; k < 4; k++){ std::cout << myResult.at(i,j,k) << " "; } std::cout << std::endl; } std::cout << std::endl; } std::cout << std::endl; return 0; } }
次のコマンドを実行して実行可能ファイルを生成します。
cfg = coder.config('exe'); cfg.TargetLang = 'C++'; cfg.CustomSource = 'xTest2_main.cpp'; cfg.CustomInclude = '.'; %current working directory codegen -config cfg -args { coder.typeof(0, [inf inf inf]), 0} xTest2_main.cpp xTest2.m -report
コード ジェネレーターによって現在の作業フォルダーに実行可能ファイル
xTest2.exe
が生成されます。
インターフェイス生成の変更
既定では、生成された C++ コードは、coder::array
テンプレートを使用して動的に割り当てられた配列を実装します。代わりに、C スタイルの emxArray
データ構造体を使用して動的に割り当てられた配列を実装する C++ コードを生成することもできます。C スタイルの emxArray
データ構造体を生成するには、次のいずれかを行います。
コード構成オブジェクト (
coder.MexCodeConfig
、coder.CodeConfig
またはcoder.EmbeddedCodeConfig
) 内でDynamicMemoryAllocationInterface
パラメーターを'C'
に設定する。MATLAB Coder™ アプリの [メモリ] タブで、[動的メモリ割り当てインターフェイス] を
[C スタイルの EmxArray を使用]
に設定する。
C スタイルの emxArray
データ構造体を使用して実装する静的に割り当てられた配列と動的に割り当てられた配列の詳細については、生成された関数インターフェイスでの C 配列の使用を参照してください。