生成されたコードにおける構造体へのデータの整理
C コードでは、構造体 (struct
) を使用してデータをメモリの連続した位置に格納します。信号や状態などのデータを意味のある名前を使用して整理できます。各構造体は名前空間として機能するため、複数のデータ項目を指定するために名前を再利用できます。配列と同様に、構造体を利用すれば、ポインターの使用によって効率的に大量のデータを転送、操作するコードを記述できます。
既定では、コード ジェネレーターはデータを標準の構造体に集約します (生成されたコードによる内部信号、状態、パラメーター データの保存方法を参照)。これらの構造体の特性を制御したり、異なる構造体を作成してこの既定の動作をオーバーライドしたりする場合は、次の表の情報を使用してください。
目的 | 手法 |
---|---|
標準のデータ構造体の特性を制御する。たとえば、構造体型の名前、構造体変数、フィールド名を指定します。 | Embedded Coder® を使用する場合、Manage Replacement of Simulink Data Types in Generated Codeを参照してください。 |
たとえば、プラグマまたはその他のコード装飾を挿入して、メモリ内の構造体の配置を制御する。 | Embedded Coder を使用する場合、Control Data and Function Placement in Memory by Inserting Pragmasを参照してください。 |
名前および他の基本特性が制御可能な構造体にデータを集約する。ブロックおよび信号をモデルに追加すると、結果の新しいデータがこれらの構造体に既定で表示される。 | Embedded Coder を使用する場合、コード マッピング エディターを使用して、構造体化されたストレージ クラスをデータのカテゴリに適用します。
コード マッピング エディターの詳細については、Configure Default C Code Generation for Categories of Data Elements and Functionsを参照してください。独自のストレージ クラスを作成するには、Define Service Interfaces, Storage Classes, Memory Sections, and Function Templates for Software Architectureを参照してください。 |
細かく制御できる特性をもつカスタム構造体に個々のデータ項目を整理して、生成されたコードの可読性を向上する。 | 必要な構造体型を表す
構造体の配列を作成するには、構造体の配列を参照してください。 |
生成されたコードと外部コード間で構造化されたデータを交換する (たとえば、外部コードで既にカスタム構造体型と対応するグローバル変数を定義している場合など)。 | 必要な構造体型を表す |
生成された関数の引数 (仮パラメーター) の数を減らす。 |
|
ルックアップ テーブル データを構造体に整理する。 | Simulink.LookupTable オブジェクトと Simulink.Breakpoint オブジェクトを使用します。Simulink.LookupTable を参照してください。 |
ビット フィールドを生成する。 | ビットフィールドおよびboolean データをビットフィールドにパッキングすることによる生成コードの最適化を参照してください。 |
構造体を作成する手法
生成されたコードで構造体を作成するには、次の手法を使用します。
コード マッピング エディターを使用して、構造体化されたストレージ クラスをデータのカテゴリに適用します。ブロックと信号をモデルに追加すると、既定の設定で新しいデータ要素がこのストレージ クラスを取得します。
モデル データ エディターを使用して、組み込みストレージ クラス
Struct
などの構造体化されたストレージ クラスを個々のデータ項目に直接適用します。カスタム非バーチャル バスおよびパラメーター構造体を作成します。
使用する手法を決定するには、次の表の情報を使用してください。
機能 | 構造体化されたストレージ クラスの既定の適用 | 構造体化されたストレージ クラスの直接適用 | 非バーチャル バスとパラメーター構造体 |
---|---|---|---|
既定の設定で新しいデータ項目を構造体に集約 | あり | なし | なし |
最適化でターゲット データの削除を回避 (生成されたコードにデータが表示されるように指定) | なし | あり | ExportedGlobal などのストレージ クラスをバスまたは構造体に直接適用する場合のみ |
ブロック線図の外観を変更せずにデータを構造体に集約 | あり | あり | なし |
信号、状態、パラメーター データを同じ構造体に配置 | なし | あり | なし |
構造体に状態のデータを含める | あり | あり | なし |
入れ子にされた構造体に構造体を整理 | なし | なし | あり |
構造体の配列に構造体を整理 | なし | なし | あり |
構造体型の名前を制御 | あり | あり。ただし、型名は指定した変数名から派生する | あり |
生成された関数で引数の数を減らす構造体を作成 | あり。ただし、Embedded Coder ディクショナリを使用して独自のストレージ クラスを作成しなければならない | なし | あり |
Embedded Coder が必要 | あり | あり | なし |
構造体化されたストレージ クラスの既定の適用
既定のストレージ クラスをモデル データのカテゴリに適用できます。モデルにブロックおよび信号を適用すると、関連付けられたデータは指定する既定のストレージ クラスを取得します。既定の設定で新しいデータを構造体に集約するには、構造体化されたストレージ クラスを適用します。クイック スタート ツールで作成したストレージ クラスの例 ParamStruct
と SignalStruct
を使用するか、Embedded Coder ディクショナリを使用して独自のストレージ クラスを作成しなければなりません。
既定の適用を使用してグローバル データ ストアまたはグローバル パラメーター (ベース ワークスペースまたはデータ ディクショナリに保存するパラメーター オブジェクト) を集約することはできません。
既定のストレージ クラスを適用にするには、コード マッピング エディターを使用します。モデル ウィンドウのアプリ ギャラリーで、[Embedded Coder] をクリックします。次に、[コード マッピング] 、 [Data Defaults] で、[Storage Class] 列を使用してストレージ クラスを適用します。
コード マッピング エディターの詳細については、Configure Default C Code Generation for Categories of Data Elements and Functionsを参照してください。Embedded Coder ディクショナリを使用して独自のストレージ クラスを作成する場合は、Create Code Definitions for Use in the Code Mappings Editorを参照してください。
構造体化されたストレージ クラスの直接適用
構造体化されたストレージ クラスを個々のデータ項目に適用できます。直接適用では、[既定のパラメーター動作] や [信号ストレージの再利用] などのコード生成最適化によって生成されたコードから各データ項目が削除されなくなります。また、直接適用では、[コード マッピング] 、 [Data Defaults] で指定する既定のストレージ クラスをオーバーライドします。
ストレージ クラスを直接適用するには、モデル データ エディター ([モデル化] タブで [モデル データ エディター] をクリック) を使用します。[ビューの変更] を [コード]
に設定し、[Storage Class] 列を使用してストレージ クラスを適用します。
Struct
の使用方法を示す例については、C コード生成のパラメーターの構成を参照してください。ストレージ クラスの適用の詳細については、Struct ストレージ クラスを使用してパラメーター データを構造体に整理するを参照してください。
非バーチャル バスとパラメーター構造体
非バーチャル バスを作成するには、Bus Creator ブロックを使用して複数の信号線を単一のバスに整理するか、Inport ブロックまたは Outport ブロックを非バーチャル バスとして設定します。構造体型を表す
Simulink.Bus
オブジェクトを作成しなければなりません。例については、信号の構造体を参照してください。非バーチャル バスの詳細については、非バーチャル バスの作成を参照してください。パラメーター構造体を作成するには、MATLAB® コマンドまたは変数エディターを使用して複数のブロック パラメーター値を MATLAB 構造体に整理します。オプションで、
Simulink.Bus
オブジェクトを作成して構造体型の名前および各フィールドのデータ型と次元などの他の特性を制御できるようにします。例については、パラメーターの構造体を参照してください。パラメーター構造体の一般情報については、関連するブロック パラメーター定義を構造体に整理を参照してください。
パラメーターの構造体
生成されたコードで構造体を作成します。構造体は、パラメーター データを格納します。
C コンストラクター
typedef struct { double G1; double G2; } myStructType; myStructType myStruct = { 2.0, -2.0 } ;
手順
1. モデル例 InlineBlockParameters
を開きます。
2. [モデル化] タブで [モデル データ エディター] をクリックします。モデル データ エディターで、[パラメーター] タブを選択します。
3. モデルで、G1
というラベルの付いた Gain ブロックをクリックします。モデル データ エディターで、[値] 列を使用して、[ゲイン] パラメーターの値を myStruct.G1
に設定します。
4. G2
ブロックの [ゲイン] パラメーターの値を myStruct.G2
に設定します。
5. myStruct.G2
の横にあるアクション ボタン (3 つの縦向きのドット) をクリックし、[作成] を選択します。
6. [新規データの作成] ダイアログ ボックスの [値] ボックスに「Simulink.Parameter(struct)
」と入力します。[場所] リストから Base Workspace
を選択します。[作成] をクリックします。myStruct
という名前の Simulink.Parameter
オブジェクトがベース ワークスペースに表示されます。
7. Simulink.Parameter プロパティのダイアログ ボックスで、[値] プロパティの横にあるアクション ボタンをクリックし、[変数エディターを開く] を選択します。
8. [フィールド] 列の下にある空白を右クリックして [新規作成] を選択します。新しい構造体フィールドに G1
という名前を付けます。[値] 列を使用して、そのフィールドの値を 2
に設定します。
9. フィールド G2
を追加してから (フィールドの値は -2
)、変数エディターを閉じます。
10. Simulink.Parameter プロパティのダイアログ ボックスの [コード生成] タブで、[ストレージ クラス] を ExportedGlobal
に設定します。構造体 myStruct
はグローバル変数として生成されたコードに表示されます。
11.モデルからコードを生成します。
結果
生成されたヘッダー ファイル InlineBlockParameters_types.h
は、ランダムな名前の構造体型を定義します。
typedef struct { real_T G1; real_T G2; } struct_6h72eH5WFuEIyQr5YrdGuB;
ソース ファイル InlineBlockParameters.c
は、構造体変数 myStruct
を定義および初期化します。
/* Exported block parameters */ struct_6h72eH5WFuEIyQr5YrdGuB myStruct = { 2.0, -2.0 } ; /* Variable: myStruct * Referenced by: * '<Root>/G1' * '<Root>/G2' */
構造体型の名前の指定
1. オプションで、構造体型定義 (struct
) を使用するために名前を指定します。コマンド プロンプトで、関数 Simulink.Bus.createObject
を使用して構造体型を表す Simulink.Bus
オブジェクトを作成します。
2. オブジェクトの既定の名前は slBus1
です。オブジェクトを新しい MATLAB® 変数にコピーして名前を変更します。
3. モデル データ エディターで [追加情報の表示/更新] ボタンをクリックします。
4. データ テーブルで myStruct
に対応する行を見つけます。[データ型] 列を使用して、myStruct
のデータ型を Bus: myStructType
に設定します。
5. モデルからコードを生成します。
コードは構造体型 myStructType
の定義を生成し、この型を使用してグローバル変数 myStruct
を定義します。
myStructType myStruct = { 2.0, -2.0 } ; /* Variable: myStruct
信号の構造体
この例では、生成されたコードで信号データの構造体を作成する方法を示します。
C コンストラクター
typedef struct { double signal1; double signal2; double signal3; } my_signals_type;
手順
モデルで構造体型を表すには、Simulink.Bus
オブジェクトを作成します。このオブジェクトをモデル内のバスのデータ型として使用します。
1. ex_signal_struct
モデルを Gain ブロック、Bus Creator ブロック、Unit Delay ブロックを使用して作成します。Gain ブロックと Unit Delay ブロックによって、生成されたコードで構造体がより識別しやすくなります。
2. 3 つの入力を受け入れるように Bus Creator ブロックを設定するには、ブロック ダイアロブ ボックスで [入力数] を 3
に設定します。
3. ツールストリップの [モデル化] タブの [設計] ギャラリーで、[型エディター] をクリックします。
4. 型エディターで、signal1
、signal2
、および signal3
という名前の要素を含む my_signals_type
という名前の Simulink.Bus
オブジェクトを作成します。詳細については、Type Editorを参照してください。
5. バス オブジェクトを現在のフォルダーに ex_signal_struct_data.mat
として保存します。
このバス オブジェクトは、生成されたコードで使用する構造体型を表します。
6. [Bus Creator ブロック] ダイアログ ボックスで、次を行います。
[出力データ型] を
Bus: my_signals_type
に設定します。[非バーチャル バスとして出力] を選択します。非バーチャル バスが生成されたコードに構造体として表示されます。
[OK] をクリックします。
7. Simulink Coder アプリを開きます。[C コード] タブで、[コード インターフェイス]、[個々の要素コードのマッピング] を選択します。
8. [信号/状態] タブを開きます。モデルで Bus Creator ブロックの出力信号を選択し、コード マッピング エディターで [選択した信号をコード マッピングに追加] ボタンをクリックします。
9. 追加された信号について [ストレージ クラス] を ExportedGlobal
に設定します。
10. プロパティ インスペクターで [コード]、[Identifier] プロパティを sig_struct_var
に設定します。Bus Creator ブロックの出力は生成されたコードに sig_struct_var
という名前の個別のグローバル構造体変数として表示されます。
11.モデルからコードを生成します。
結果
生成されたヘッダー ファイル ex_signal_struct_types.h
は構造体型 my_signals_type
を定義します。
typedef struct { real_T signal1; real_T signal2; real_T signal3; } my_signals_type;
ソース ファイル ex_signal_struct.c
は、Bus Creator ブロックの出力を表すグローバル変数 sig_struct_var
にメモリを割り当てます。
/* Exported block signals */ my_signals_type sig_struct_var; /* '<Root>/Bus Creator' */
同じファイル内のモデルの関数 step
で、アルゴリズムは sig_struct_var
と sig_struct_var
のフィールドにアクセスします。
信号の入れ子にされた構造体
生成されたコードで信号データの入れ子にされた構造体を作成できます。
C コンストラクター
typedef struct { double signal1; double signal2; double signal3; } B_struct_type; typedef struct { double signal1; double signal2; } C_struct_type; typedef struct { B_struct_type subStruct_B; C_struct_type subStruct_C; } A_struct_type;
手順
モデルで構造体型を表すには、Simulink.Bus
オブジェクトを作成します。このオブジェクトをモデル内のバスのデータ型として使用します。
別の構造体内に構造体を入れ子にするには、別のバス オブジェクト内でバス オブジェクトを要素のデータ型として使用します。
1. ex_signal_nested_struct
モデルを Gain ブロック、Bus Creator ブロック、Unit Delay ブロックで作成します。Gain ブロックと Unit Delay ブロックによって、生成されたコードで構造体がより識別しやすくなります。
3 つの入力を受け入れるように Bus Creator ブロックを設定するには、ブロック ダイアロブ ボックスで [入力数] を 3
に設定します。
2. ツールストリップの [モデル化] タブの [設計] ギャラリーで、[型エディター] をクリックします。
3. 型エディターで、Simulink.Bus
オブジェクトを 3 つ作成します。
subStruct_B
およびsubStruct_C
という名前の 2 つの要素を含むA_struct_type
という名前のバス オブジェクトsignal1
、signal2
、およびsignal3
という名前の 3 つの要素を含むB_struct_type
という名前のバス オブジェクトsignal1
およびsignal2
という名前の 2 つの要素を含むC_struct_type
という名前のバス オブジェクト
A_struct_type
という名前のバス オブジェクトは、生成されたコードで使用する最上位構造体型を表します。
バス オブジェクトとその要素の作成方法については、Type Editorを参照してください。
4. A_struct_type
オブジェクトで、他のバス オブジェクトをデータ型として使用します。
subStruct_B
要素について、[データ型] をBus: B_struct_type
に設定します。subStruct_C
要素について、[データ型] をBus: C_struct_type
に設定します。
A_struct_type
の各要素は別のバス オブジェクトをデータ型として使用します。これらの要素はサブ構造体を表します。
5. 3 つの Gain ブロックから信号を受け取る Bus Creator ブロックのダイアログ ボックスで、次を行います。
[出力データ型] を
Bus: B_struct_type
に設定します。[非バーチャル バスとして出力] を選択します。
[OK] をクリックします。
6. 他の下位の Bus Creator ブロックのダイアログ ボックスで、次を行います。
[出力データ型] を
Bus: C_struct_type
に設定します。[非バーチャル バスとして出力] を選択します。
[OK] をクリックします。
7. 最後の [Bus Creator ブロック] ダイアログ ボックスで、次を行います。
[出力データ型] を
Bus: A_struct_type
に設定します。[非バーチャル バスとして出力] を選択します。
[OK] をクリックします。
8. Simulink Coder アプリを開きます。[C コード] タブで、[コード インターフェイス]、[個々の要素コードのマッピング] を選択します。
9. [信号/状態] タブを開きます。モデルで、Unit Delay ブロックに接続する A_struct_type
Bus Creator ブロックの出力信号を選択します。コード マッピング エディターで、[選択した信号をコード マッピングに追加] ボタンをクリックします。
10. 追加された信号について [ストレージ クラス] を ExportedGlobal
に設定します。
11.プロパティ インスペクターで [コード]、[Identifier] プロパティを sig_struct_var
に設定します。Bus Creator ブロックの出力は生成されたコードに sig_struct_var
という名前の個別のグローバル構造体変数として表示されます。
12.モデルからコードを生成します。
結果
生成されたヘッダー ファイル ex_signal_nested_struct_types.h
は構造体型を定義します。各構造体型は Simulink.Bus
オブジェクトに対応します。
typedef struct { real_T signal1; real_T signal2; real_T signal3; } B_struct_type; typedef struct { real_T signal1; real_T signal2; } C_struct_type; typedef struct { B_struct_type subStruct_B; C_struct_type subStruct_C; } A_struct_type;
生成されたソース ファイル ex_signal_nested_struct.c
はグローバル構造体変数 sig_struct_var
にメモリを割り当てます。既定では、A_struct_type
Bus Creator ブロックの名前は Bus Creator2
です。
/* Exported block signals */ A_struct_type sig_struct_var; /* '<Root>/Bus Creator2' */
同じファイル内のモデルの関数 step
で、アルゴリズムは sig_struct_var
と sig_struct_var
のフィールドにアクセスします。
制限を回避する手法の組み合わせ
各手法の制限を回避するために、構造体化されたストレージ クラスを非バーチャル バスおよびパラメーター構造体と組み合わせることができます。たとえば、次のようなことができます。
信号データの構造体とパラメーター データの構造体を同じ親構造体に含める。
既定の設定で新しいデータの集約し、さらに構造体を入れ子にする。
生成されたコードでは、構造体化されたストレージ クラスに対応するフラットな親構造体に、各バスとパラメーター構造体に対応するサブ構造体が含まれています。次のいずれかの手法の組み合わせを選択します。
構造体化されたストレージ クラスを各バスとパラメーター構造体に直接適用します。たとえば、2 つの非バーチャル バス信号のストレージ クラスを
Struct
に設定します。各バスは生成されたコードで単一の構造体のフィールド (サブ構造体) として表示されます。各バスとパラメーター構造体のストレージ クラスを既定の設定
[Auto]
または[Model default]
のままにし、コード生成最適化によってバスまたはパラメーター構造体が削除されないようにします。次に、信号データとパラメーター データが構造体化されたストレージ クラスを既定で使用するように、既定のストレージ クラスを設定します。
構造体の配列
複数の一貫性のあるバス信号またはパラメーター構造体を配列にさらにパッケージ化できます。バス配列またはパラメーター構造体は構造体の配列として生成されたコードに表示されます。バス配列を作成するには、非バーチャル バスのバス配列へのグループ化を参照してください。パラメーター構造体の配列を作成する場合は、複数のパラメーター構造体を配列にグループ化を参照してください。
構造体のパディング
既定では、コード ジェネレーターは構造体型にパディング フィールドを明示的に追加することはありません。構造体型は、たとえば、標準のデータ構造体 (生成されたコードにおけるデータ構造体を参照)、Simulink.Bus
オブジェクトおよびモデルで使用するパラメーター構造体を介して生成されたコードに表示されることがあります。
ただし、Embedded Coder でコード置換ライブラリを使用する場合、データ配置 (構造体のパディングを含む) を置換ライブラリの一部として指定できます。詳細については、Provide Data Alignment Specifications for Compilersを参照してください。
制限
組み込みの Simulink® Coder™ 機能と Embedded Coder 機能では、値がポインターのフィールドが含まれるカスタム構造体を生成または使用することはできません。これは、高度なストレージ クラスを作成し、付随する TLC コードを書き込むことによって手動で行うことができます (ストレージ クラスの TLC コードの記述によるデータ表現の詳細な制御を参照)。
組み込みストレージ クラス
Struct
またはカスタム ストレージ クラス デザイナーで作成する構造体化されたストレージ クラスを使用して (ストレージ クラス プロパティ [種類] を[FlatStructure]
に設定)、コード マッピング エディターでデータの既定を設定することはできません。