生成された関数インターフェイスでの動的に割り当てられた 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 多次元配列にインデックスを付けるには、 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"に設定する。[コード生成設定] ダイアログ ボックスで、[動的メモリ割り当てインターフェイス] パラメーターを
[C スタイルの EmxArray を使用]に設定する。
C スタイルの emxArray データ構造体を使用して実装する静的に割り当てられた配列と動的に割り当てられた配列の詳細については、生成される関数インターフェイスでの動的に割り当てられる C 配列の使用を参照してください。