Main Content

生成されたコードにおける構造体へのデータの整理

C コードでは、構造体 (struct) を使用してデータをメモリの連続した位置に格納します。信号や状態などのデータを意味のある名前を使用して整理できます。各構造体は名前空間として機能するため、複数のデータ項目を指定するために名前を再利用できます。配列と同様に、構造体を利用すれば、ポインターの使用によって効率的に大量のデータを転送、操作するコードを記述できます。

既定では、コード ジェネレーターはデータを標準の構造体に集約します (生成されたコードによる内部信号、状態、パラメーター データの保存方法を参照)。これらの構造体の特性を制御したり、異なる構造体を作成してこの既定の動作をオーバーライドしたりする場合は、次の表の情報を使用してください。

目的 手法

標準のデータ構造体の特性を制御する。たとえば、構造体型の名前、構造体変数、フィールド名を指定します。

Embedded Coder®を使用する場合、Control Data Type Names in Generated Code(Embedded Coder)を参照してください。

たとえば、プラグマまたはその他のコード装飾を挿入して、メモリ内の構造体の配置を制御する。

Embedded Coder を使用する場合、Control Data and Function Placement in Memory by Inserting Pragmas(Embedded Coder)を参照してください。

名前および他の基本特性が制御可能な構造体にデータを集約する。ブロックおよび信号をモデルに追加すると、結果の新しいデータがこれらの構造体に既定で表示される。

Embedded Coder を使用する場合、コード マッピング エディターを使用して、構造化されたストレージ クラスをデータのカテゴリに適用します。

  • モデル コンフィギュレーション パラメーターの[コード インターフェイスのパッケージ化][再利用できない関数]に設定して再利用できない単一インスタンスのコードを生成する場合、組み込みストレージ クラスStructを適用して、フラットなグローバル構造体変数を作成します。または、クイック スタート ツールで作成したストレージ クラスの例ParamStructSignalStructを使用するか、独自の構造化されたストレージ クラスを適用します。

  • たとえば、[コード インターフェイスのパッケージ化][再利用できない関数]以外の値に設定して、モデルまたはコンポーネントからマルチインスタンス (再呼び出し可能な) コードを生成する場合、コード マッピング エディターでは、組み込みストレージ クラスStructまたはパッケージで作成する構造化されたストレージ クラスを使用することはできません。代わりに、Embedded Coder ディクショナリを使用して独自の構造化されたストレージ クラスを作成します。Embedded Coder クイック スタート ツールを使用してコード生成用のモデルを準備する場合 (クイック スタート ツールを使用したコードの生成(Embedded Coder)を参照)、ストレージ クラスの例ParamStructSignalStructを使用できます。

  • この手法を使用してグローバル データ ストアまたはグローバル パラメーターを集約することはできません (ベース ワークスペースまたはデータ ディクショナリに保存するパラメーター オブジェクトも含む)。これらの種類のデータについては、他の手法を使用して構造体を作成してください。

コード マッピング エディターの詳細については、Configure Default C Code Generation for Categories of Data Elements and Functions(Embedded Coder)を参照してください。独自のストレージ クラスを作成するには、Define Storage Classes, Memory Sections, and Function Templates for Software Architecture(Embedded Coder)を参照してください。

細かく制御できる特性をもつカスタム構造体に個々のデータ項目を整理して、生成されたコードの可読性を向上する。

必要な構造体型を表すSimulink.Busオブジェクトを作成します。バス オブジェクトを使用して、非バーチャル バス信号のデータ型およびパラメーター構造体をモデルで設定します。

  • パラメーター データの整理方法を示す例については、パラメーターの構造体を参照してください。

  • 信号データの整理方法を示す例については、信号の構造体を参照してください。

構造体の配列を作成するには、構造体の配列を参照してください。

生成されたコードと外部コード間で構造化されたデータを交換する (たとえば、外部コードで既にカスタム構造体型と対応するグローバル変数を定義している場合など)。

必要な構造体型を表すSimulink.Busオブジェクトを作成します。外部コードで既に型を定義している場合、関数Simulink.importExternalCTypesを使用してバス オブジェクトを生成します。バス オブジェクトを使用して、非バーチャル バス信号のデータ型およびパラメーター構造体をモデルで設定します。例については、Exchange Structured and Enumerated Data Between Generated and External Code(Embedded Coder)を参照してください。

生成された関数の引数 (仮パラメーター) の数を減らす。

  • model_stepなど、コードを生成するモデルのエントリポイント関数に対する引数の数を減らすには、構造体を使用した引数の数の削減を参照してください。

  • 参照モデルのエントリポイント関数に対する引数の数を減らす場合は、参照モデルで次のようにします。

  • 再呼び出し可能なマスク サブシステムのエントリポイント関数の引数の数を減らすには、マスク パラメーターをカスタム構造体に集約します。

ルックアップ テーブル データを構造体に整理する。

Simulink.LookupTableオブジェクトとSimulink.Breakpointオブジェクトを使用します。Simulink.LookupTableを参照してください。
ビット フィールドを生成する。 Bitfields(Embedded Coder)およびOptimize Generated Code by Packing Boolean Data into Bitfields(Embedded Coder)を参照してください。

構造体を作成する手法

生成されたコードで構造体を作成するには、次の手法を使用します。

  • コード マッピング エディターを使用して、構造化されたストレージ クラスをデータのカテゴリに適用します。ブロックと信号をモデルに追加すると、既定の設定で新しいデータ要素がこのストレージ クラスを取得します。

  • モデル データ エディターを使用して、組み込みストレージ クラスStructなどの構造化されたストレージ クラスを個々のデータ項目に直接適用します。

  • カスタム非バーチャル バスおよびパラメーター構造体を作成します。

使用する手法を決定するには、次の表の情報を使用してください。

機能 構造化されたストレージ クラスの既定の適用 構造化されたストレージ クラスの直接適用 非バーチャル バスとパラメーター構造体
既定の設定で新しいデータ項目を構造体に集約

あり

なし なし
最適化でターゲット データの削除を回避 (生成されたコードにデータが表示されるように指定)

なし

あり ExportedGlobalなどのストレージ クラスをバスまたは構造体に直接適用する場合のみ
ブロック線図の外観を変更せずにデータを構造体に集約

あり

あり なし
信号、状態、パラメーター データを同じ構造体に配置 なし あり なし
構造体に状態のデータを含める あり あり なし
入れ子にされた構造体に構造体を整理 なし なし あり
構造体の配列に構造体を整理 なし なし あり
構造体型の名前を制御

あり

あり。ただし、型名は指定した変数名から派生する あり
生成された関数で引数の数を減らす構造体を作成

あり。ただし、Embedded Coder ディクショナリを使用して独自のストレージ クラスを作成しなければならない

なし あり
Embedded Coder が必要 あり あり なし

構造化されたストレージ クラスの既定の適用

既定のストレージ クラスをモデル データのカテゴリに適用できます。モデルにブロックおよび信号を適用すると、関連付けられたデータは指定する既定のストレージ クラスを取得します。既定の設定で新しいデータを構造体に集約するには、構造化されたストレージ クラスを適用します。クイック スタート ツールで作成したストレージ クラスの例ParamStructSignalStructを使用するか、Embedded Coder ディクショナリを使用して独自のストレージ クラスを作成しなければなりません。

既定の適用を使用してグローバル データ ストアまたはグローバル パラメーター (ベース ワークスペースまたはデータ ディクショナリに保存するパラメーター オブジェクト) を集約することはできません。

既定のストレージ クラスを適用にするには、コード マッピング エディターを使用します。モデル ウィンドウのアプリ ギャラリーで、[Embedded Coder]をクリックします。次に、[コード マッピング][Data Defaults]で、[Storage Class]列を使用してストレージ クラスを適用します。

コード マッピング エディターの詳細については、Configure Default C Code Generation for Categories of Data Elements and Functions(Embedded Coder)を参照してください。Embedded Coder ディクショナリを使用して独自のストレージ クラスを作成する場合は、Create Code Definitions for Use in the Code Mappings Editor(Embedded Coder)を参照してください。

構造化されたストレージ クラスの直接適用

構造化されたストレージ クラスを個々のデータ項目に適用できます。直接適用では、[既定のパラメーター動作][信号ストレージの再利用]などのコード生成最適化によって生成されたコードから各データ項目が削除されなくなります。また、直接適用では、[コード マッピング][Data Defaults]で指定する既定のストレージ クラスをオーバーライドします。

ストレージ クラスを直接適用するには、モデル データ エディター ([モデル化]タブで[モデル データ エディター]をクリック) を使用します。[ビューの変更][コード]に設定し、[Storage Class]列を使用してストレージ クラスを適用します。

Structの使用方法を示す例については、C コード生成のパラメーターの構成(Embedded Coder)を参照してください。ストレージ クラスの適用の詳細については、Struct ストレージ クラスを使用してパラメーター データを構造体に整理する(Embedded Coder)を参照してください。

非バーチャル バスとパラメーター構造体

  • 非バーチャル バス信号を作成するには、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. モデル例rtwdemo_paraminlineを開きます。

2.[モデル化]タブで[モデル データ エディター]をクリックします。モデルデータエディターで、[パラメーター]タブを選択します。

3.モデルで、G1というラベルの付いた Gain ブロックをクリックします。モデル データ エディターで、[値]列を使用して、[ゲイン]パラメーターの値をmyStruct.G1に設定します。

4.G2ブロックの[ゲイン]パラメーターの値をmyStruct.G2に設定します。

5.myStruct.G2の横にあるアクション ボタン (3 つの縦向きのドット) をクリックし、[作成]を選択します。

6. [新規データの作成] ダイアログ ボックスで、[値]Simulink.Parameter(struct)に設定して[作成]をクリックします。myStructという名前のSimulink.Parameterオブジェクトがベース ワークスペースに表示されます。

7. Simulink.Parameter プロパティのダイアログ ボックスで、[値]プロパティの横にあるアクション ボタンをクリックし、[変数エディターを開く]を選択します。

8.[フィールド]列の下にある空白を右クリックして[新規作成]を選択します。新しい構造体フィールドにG1という名前を付けます。[値]列を使用して、そのフィールドの値を2に設定します。

9. フィールドG2を追加してから (フィールドの値は-2)、変数エディターを閉じます。

10. Simulink.Parameter プロパティのダイアログ ボックスの[コード生成]タブで、[ストレージ クラス]ExportedGlobalに設定します。構造体myStructはグローバル変数として生成されたコードに表示されます。

11.モデルからコードを生成します。

結果

生成されたヘッダー ファイルrtwdemo_paraminline_types.hは、ランダムな名前の構造体型を定義します。

typedef struct { real_T G1; real_T G2; } struct_6h72eH5WFuEIyQr5YrdGuB;

ソース ファイルrtwdemo_paraminline.cは、構造体変数myStructを定義および初期化します。

/* Exported block parameters */ struct_6h72eH5WFuEIyQr5YrdGuB myStruct = { 2.0, -2.0 } ; /* Variable: myStruct * Referenced by: * '/G1' * '/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. バス エディター ツールストリップの、[追加]ギャラリーで、[バス]をクリックしてSimulink.Busオブジェクトを作成します。その後、名前をmy_signals_typeにします。my_signals_typeを選択した状態で、[追加]ギャラリーで、[バス要素]を 3 回クリックし、3 つの要素を追加します。名前をsignal1signal2、およびsignal3にします。詳細については、バス エディターを参照してください。

5. バス オブジェクトを現在のフォルダーにex_signal_struct_data.matとして保存します。

このバス オブジェクトは、生成されたコードで使用する構造体型を表します。

6. Bus Creator ブロックのダイアログ ボックスで、[出力データ型]Bus: my_signals_typeに設定します。

7.[非バーチャル バスとして出力]を選択します。[OK]をクリックします。非バーチャル バスが生成されたコードに構造体として表示されます。

8.Simulink Coderアプリを開きます。[C コード]タブで、[コード インターフェイス][個々の要素コードのマッピング]を選択します。

9.[信号/状態]タブを開きます。モデルで Bus Creator ブロックの出力信号を選択し、コード マッピング エディターで[選択した信号をコード マッピングに追加]ボタンをクリックします。

11.追加された信号について[ストレージ クラス]ExportedGlobalに設定します。

12.プロパティ インスペクターで[コード][Identifier]プロパティをsig_struct_varに設定します。Bus Creator ブロックの出力は生成されたコードにsig_struct_varという名前の個別のグローバル構造体変数として表示されます。

13.モデルからコードを生成します。

結果

生成されたヘッダー ファイル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; /* '/Bus Creator' */

同じファイル内のモデルの関数stepで、アルゴリズムはsig_struct_varsig_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 ブロックによって、生成されたコードで構造体がより識別しやすくなります。

2. 3 つの入力を受け入れるように Bus Creator ブロックを設定するには、ブロック ダイアロブ ボックスで[入力数]3に設定します。

3.ツールストリップの[モデル化]タブの[設計]で、[バス エディター]をクリックします。

バス エディター ツールストリップの、[追加]ギャラリーで、[バス]をクリックしてSimulink.Busオブジェクトを作成します。その後、名前をA_struct_typeにします。A_struct_typeを選択した状態で、[追加]ギャラリーで、[バス要素]を 2 回クリックし、2 つの要素を追加します。要素にsubStruct_BおよびsubStruct_Cという名前を付けます。詳細については、バス エディターを参照してください。このバス オブジェクトは、生成されたコードで使用する最上位構造体型を表します。

4. 同様に、Simulink.BusオブジェクトB_struct_type(3 つの要素をもつ) およびC_struct_type(2 つの要素をもつ) を作成します。

5.A_struct_typeオブジェクトで、subStruct_B要素について、[データ型]Bus: B_struct_typeに設定します。同様に、subStruct_C要素について、[データ型]Bus: C_struct_typeに設定します。

A_struct_typeの各要素は別のバス オブジェクトをデータ型として使用します。これらの要素はサブ構造体を表します。

6. 3 つの Gain 信号を収集する Bus Creator ブロックのダイアログ ボックスで、[出力データ型]Bus: B_struct_typeに設定します。[適用]をクリックします。

7.[非バーチャル バスとして出力]を選択し、[OK]をクリックします。

8. 他の下位の Bus Creator ブロック ダイアログ ボックスで、[出力データ型]Bus: C_struct_typeに設定し、[非バーチャル バスとして出力]を選択します。[OK]をクリックします。

9. 最後の Bus Creator ブロック ダイアログ ボックスで、[出力データ型]Bus: A_struct_typeに設定し、[非バーチャル バスとして出力]を選択します。[OK]をクリックします。

10.Simulink Coderアプリを開きます。[C コード]タブで、[コード インターフェイス][個々の要素コードのマッピング]を選択します。

11.[信号/状態]タブを開きます。モデルで、Unit Delay ブロックに接続するA_struct_typeBus Creator ブロックの出力信号を選択します。コード マッピング エディターで、[選択した信号をコード マッピングに追加]ボタンをクリックします。

12.追加された信号について[ストレージ クラス]ExportedGlobalに設定します。

13.プロパティ インスペクターで[コード][Identifier]プロパティをsig_struct_varに設定します。Bus Creator ブロックの出力は生成されたコードにsig_struct_varという名前の個別のグローバル構造体変数として表示されます。

14.モデルからコードを生成します。

結果

生成されたヘッダー ファイル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_typeBus Creator ブロックの名前はBus Creator2です。

/* Exported block signals */ A_struct_type sig_struct_var; /* '/Bus Creator2' */

同じファイル内のモデルの関数stepで、アルゴリズムはsig_struct_varsig_struct_varのフィールドにアクセスします。

制限を回避する手法の組み合わせ

各手法の制限を回避するために、構造化されたストレージ クラスを非バーチャル バスおよびパラメーター構造体と組み合わせることができます。たとえば、次のようなことができます。

  • 信号データの構造体とパラメーター データの構造体を同じ親構造体に含める。

  • 既定の設定で新しいデータの集約し,さらに構造体を入れ子にする。

生成されたコードでは、構造化されたストレージ クラスに対応するフラットな親構造体に、各バスとパラメーター構造体に対応するサブ構造体が含まれています。次のいずれかの手法の組み合わせを選択します。

  • 構造化されたストレージ クラスを各バスとパラメーター構造体に直接適用します。たとえば、2 つの非バーチャル バス信号のストレージ クラスをStructに設定します。各バスは生成されたコードで単一の構造体のフィールド (サブ構造体) として表示されます。

  • 各バスとパラメーター構造体のストレージ クラスを既定の設定[Auto]または[Model default]のままにし、コード生成最適化によってバスまたはパラメーター構造体が削除されないようにします。次に、信号データとパラメーター データが構造化されたストレージ クラスを既定で使用するように、既定のストレージ クラスを設定します。

構造体の配列

複数の一貫性のあるバス信号またはパラメーター構造体を配列にさらにパッケージ化できます。バス配列またはパラメーター構造体は構造体の配列として生成されたコードに表示されます。バス配列を作成するには、非バーチャル バスのバス配列へのグループ化を参照してください。パラメーター構造体の配列を作成する場合は、複数のパラメーター構造体を配列にグループ化を参照してください。

構造体のパディング

既定では、コード ジェネレーターは構造体型にパディング フィールドを明示的に追加することはありません。構造体型は、たとえば、標準のデータ構造体 (生成されたコードにおけるデータ構造体を参照)、Simulink.Busオブジェクトおよびモデルで使用するパラメーター構造体を介して生成されたコードに表示されることがあります。

ただし、Embedded Coder でコード置換ライブラリを使用する場合、データ配置 (構造体のパディングを含む) を置換ライブラリの一部として指定できます。詳細については、Provide Data Alignment Specifications for Compilers(Embedded Coder)を参照してください。

制限

  • 組み込みの金宝app®Coder™機能と Embedded Coder 機能では、値がポインターのフィールドが含まれるカスタム構造体を生成または使用することはできません。これは、高度なストレージ クラスを作成し、付随する TLC コードを書き込むことによって手動で行うことができます (ストレージ クラスの TLC コードの記述によるデータ表現の詳細な制御(Embedded Coder)を参照)。

  • 組み込みストレージ クラスStructまたはカスタム ストレージ クラス デザイナーで作成する構造化されたストレージ クラスを使用して (ストレージ クラス プロパティ[種類][FlatStructure]に設定)、コード マッピング エディターでデータの既定を設定することはできません。

参考

関連するトピック