Main Content

生成コードでのデータと関数インターフェイスの制御

モデルから生成するコードを使用するには、stepinitialize などの生成されたエントリポイント関数を呼び出します。呼び出し環境および生成された関数は、入出力データをグローバル変数または仮パラメーター (引数) を介して交換します。このデータおよび交換メカニズムは、エントリポイント関数のインターフェイスを構成します。生成されたコードの再呼び出し可能なモデルと再呼び出し不可能なモデルの既定のインターフェイスの詳細については、生成されたコードによる環境とのデータ交換方法を参照してください。

生成されたコードに表示されるインターフェイスを制御することで以下が可能です。

  • 既存のコードに行わなければならない変更の最小化。

  • モデルに変更を行う場合に、変更しない、あるいは最小限の変更しか行わない、安定したインターフェイスの生成。

  • データをより効率的に交換するコードの生成 (たとえば、非スカラー データに対するポインターおよび参照渡しの引数の使用による)。

標準の I/O 構造体のタイプ名、フィールド名および変数名の制御 (Embedded Coder)

既定では、再呼び出し不可能なコードの場合、モデルのルート レベルの Inport ブロックは、グローバル構造体変数のフィールドとして生成されたコードに表示されます。同様に、Outport ブロックは異なる構造体内に表示されます。再呼び出し可能なコードの場合、モデル コンフィギュレーション パラメーター [ルートレベル I/O を以下として渡す:] の設定に応じて、コード ジェネレーターは入出力データを標準の構造体にパッケージ化することもできます。

Embedded Coder® を使用すると、これらの名前を制御できます。Control Data Type Names in Generated Code (Embedded Coder)を参照してください。

生成されたエントリポイント関数の名前の制御 (Embedded Coder)

生成コードを使用するには、生成されたエントリポイント関数を呼び出すコードを作成します。たとえば、エントリポイント関数に model_stepmodel_initialize、およびエクスポート関数モデルから生成された最上位関数が含まれます。モデル エントリポイント関数の名前を制御するには、コード マッピング エディター (Embedded Coder が必要) を使用して以下の方法の組み合わせを適用します。

  • [関数の既定の設定] タブで、コード マッピング エディターで関数カスタマイズ テンプレートを適用し、エントリポイント関数のカテゴリに既定の命名規則を指定します。この方法により、命名規則がカテゴリ内の関数に適用されます。詳細については、Configure Default Code Generation for Functions (Embedded Coder)を参照してください。

  • [関数] タブで、[関数名] 列を直接編集するか、[関数プレビュー] 列から開いた設定ダイアログ ボックスを介して個々のエントリポイント関数の名前を指定します。指定する名前は、関数カスタマイズ テンプレートで指定される既定の命名規則をオーバーライドします。詳細については、生成された C 関数インターフェイスをモデルのエントリポイント関数用に構成 (Embedded Coder)を参照してください。

再呼び出し不可能なコードのデータ インターフェイスの制御

モデル コンフィギュレーション パラメーター [コード インターフェイスのパッケージ化][再利用できない関数] (既定の設定) に設定する場合、生成されたエントリポイント関数は再呼び出し可能ではありません。通常、関数は、グローバル変数に直接アクセスして呼び出し環境とデータを交換します。

Inport ブロックまたは Outport ブロックの別個のグローバル変数としての設定

別個のグローバル変数を作成することで標準の I/O 構造体からブロックを削除するには、ExportedGlobalExportToFile などのストレージ クラスをブロックが表す信号に適用します。Inport ブロックなどの、データ要素のカテゴリについての既定のストレージ クラスを構成できます。これらのブロックをモデルに追加すると、指定したストレージ クラスが取得されます。コード マッピング エディターを使用して、個別のブロックを構成することもできます。モデルにごく少数の特定のカテゴリのデータ要素しかない場合には、この方法を行うか、または既定の構成の設定をオーバーライドします。

例については、Inport ブロックと Outport ブロックの設定によるデータ インターフェイスの設計を参照してください。コード生成のためのデータの構成の一般的な詳細については、モデル インターフェイス要素の C コード生成の構成を参照してください。

外部コードによって定義されたグローバル変数の読み取りまたは書き込みを行うための生成コードの設定

呼び出しコードが、生成されたコードが入力データとして使用したり、出力データを格納するために使用したりするグローバル変数を既に定義している場合、コード ジェネレーターに定義を複製させないようにすることで、その変数を再利用できます。ストレージ クラスをモデルの対応する Inport ブロックまたは Outport ブロックに適用します。ImportedExtern または ImportFromFile などのインポートされたデータ スコープを指定するストレージ クラスを選択します。ストレージ クラスの適用の詳細については、モデル インターフェイス要素の C コード生成の構成およびStruct ストレージ クラスを使用してパラメーター データを構造体に整理する (Embedded Coder)を参照してください。

複数の入力または出力のカスタム構造体へのパッケージ化

1 つの Inport ブロックまたは Outport ブロックが、複数の入力または出力信号を含むカスタム構造体として生成されたコードに表示されるように設定できます。また、このブロックが既定の I/O 構造体または別個の構造体変数のサブ構造体として表示されるように設定することもできます。

Simulink.Bus オブジェクトをブロックのデータ型として使用することで、非バーチャル バスとしてブロックを設定します。外部コードが構造型を定義する場合、関数 Simulink.importExternalCTypes を使用してバス オブジェクトを生成することを検討してください。

  • バス信号を標準の I/O 構造体のサブ構造体として生成するには、ブロック ストレージ クラスの既定の設定である [Auto] のままにしておきます。Embedded Coder がある場合は、コード マッピング エディターの [Data Defaults] タブで、カテゴリ [入力端子][出力端子] のストレージ クラスを [Default] に設定します。

  • バス信号を別個のグローバル構造体変数として生成するには、ExportedGlobalExportToFile などのストレージ クラスを適用します。

生成されたコードにおいて信号をカスタム構造体にグループ化する詳細については、生成されたコードにおける構造体へのデータの整理を参照してください。

Inport ブロックまたは Outport ブロックの関数呼び出しとしての設定 (Embedded Coder)

外部コードが、生成されたコードで作成された入力データを返したり、出力データを受け入れる関数を定義したりする場合、Inport ブロックまたは Outport ブロックを設定し、生成されたコードがグローバル変数にアクセスせずに関数の呼び出しができます。Embedded Coder ストレージ クラス GetSet を適用します。詳細については、Access Data Through Functions with Storage Class GetSet (Embedded Coder)を参照してください。

関数の引数を使用した入力と出力の引き渡し (Embedded Coder)

Embedded Coder では、オプションでモデルのステップ (実行) 関数を構成し、グローバル変数に対する読み取りと書き込みを直接実行せずに、引数を介してルートレベルの入力と出力にアクセスできます。名前、順序、引き渡しメカニズム (参照渡しまたは値渡し) などの引数の特性を完全に制御します。この構成レベルは生成コードと外部コードの統合に役立ちます。

引数を介して入力と出力を引き渡すには、[C ステップ関数インターフェイスを設定] ダイアログ ボックスで [ステップ関数プロトタイプの引数を設定] を選択します。モデルのルート レベルの各 Inport ブロックと Outport ブロックは、実行関数の引数としてコードに表示されます。詳細については、生成された C 関数インターフェイスをモデルのエントリポイント関数用に構成 (Embedded Coder)を参照してください。

グローバル変数としての参照モデルの入力と出力の構成 (void-void)

既定では、再呼び出し不可能な参照モデルの場合、生成コードは関数引数を使ってルートレベルの入力と出力を引き渡します。再呼び出し不可能な参照モデルは、モデル コンフィギュレーション パラメーター [最上位モデルごとに可能なインスタンスの総数][1] に設定する参照モデルです。

代わりに (void-void インターフェイスで) グローバル変数を使ってこのデータを引き渡すには、参照モデルで、ExportedGlobalExportToFile などのストレージ クラスをルートレベルの Inport ブロックと Outport ブロックに適用します。

  • 既定のストレージ クラスをこのようなブロックに適用するには、コード マッピング エディターを使用します。この方法では、これらのブロックをモデルに追加すると、ブロックは既定のストレージ クラスを取得し、void-void インターフェイスを保持します。詳細については、Configure Default Code Generation for Data (Embedded Coder)を参照してください。

  • 既定のストレージ クラスをオーバーライドするには、コード マッピング エディターを使用してストレージ クラスを個別のブロックに直接適用します。モデル インターフェイス要素の C コード生成の構成を参照してください。

  • Embedded Coder を必要とする例については、Establish Data Ownership in a Model Hierarchy (Embedded Coder)を参照してください。

再呼び出し可能なコードのデータ インターフェイスの制御

[コード インターフェイスのパッケージ化][再利用可能な関数] に設定すると、生成されたエントリポイント関数は再呼び出し可能になります。この関数は、仮パラメーター (引数) を介して呼び出し環境とデータを交換します。既定では、各ルートレベルの Inport ブロックおよび Outport ブロックは、標準の I/O 構造体のフィールドではなく、別個の引数として、生成されたコードに表示されます。

インターフェイスに対する意図しない変更の回避

モデルへの変更のいくつかは、生成コードのエントリポイント関数インターフェイスを変えてしまいます。たとえば、モデルの名前を変更すると、関数の名前が変わる場合があります。引数を使ってデータを交換するようモデルのコードを構成している場合、Inport ブロックまたは Outport ブロックを追加または削除したり、ブロックの名前を変更すると、対応する引数が変わる場合があります。

呼び出しコードの保守をより簡単にするには、エントリポイント関数のインターフェイスへの変更を防止します。

  • 入力データと出力データを引数を使って交換する場合は、Inport ブロックと Outport ブロックをそれぞれ個別の引数として表示できる (既定の設定) ようにするのではなくこれらのブロックを構造体にパッケージ化するよう生成コードを構成します。この場合、Inport ブロックまたは Outport ブロックを追加または削除したり、名前やデータ型などのプロパティを変更したりすると、構造体のフィールドは変わりますが、関数インターフェイスは変わりません。構造体を使用した引数の数の削減を参照してください。

  • Inport ブロックおよび Outport ブロックのデータ型を明示的に設定し、継承されたデータ型設定 (これらのブロックが既定で使用する) を使用しません。継承されたデータ型設定により、ブロックは上流および下流信号のデータ型に応じて異なるデータ型を使用する可能性があります。データ型の設定の詳細については、信号のデータ型の制御を参照してください。

  • Embedded Coder で、モデル名に依存しない関数名を指定します。関数のカスタマイズ テンプレートで命名規則を指定する場合は、規則にトークン $R を使用しないでください。生成されたエントリポイント関数の名前の制御 (Embedded Coder)を参照してください。

構造体を使用した引数の数の削減

関数の引数の数を削減すると、コードの可読性が向上し、スタック メモリの使用量が削減されます。データの複数の部分を一度に引き渡すことができる構造体の引数を作成するには、次の方法を使用します。

  • 複数の Inport ブロックまたは Outport ブロックを組み合わせて、それらのブロックが構造体のフィールドまたは標準のデータ構造体のサブ構造体として生成コードに表示されるようにします。1 つ以上の生成されたエントリポイント関数は、構造体のアドレスを別個の引数または標準の I/O 構造体のサブ構造体 (フィールド) として受け入れます。

    Inport ブロックと Outport ブロックを単一のブロックに置き換え、Simulink.Bus オブジェクトをブロックのデータ型として使用することで、非バーチャル バスとして新しいブロックを設定します。外部コードが構造型を定義する場合、関数 Simulink.importExternalCTypes を使用してバス オブジェクトを生成することを検討してください。生成されたコードにおける構造体へのデータの整理および Simulink.importExternalCTypes を参照してください。

  • Embedded Coder で再呼び出し可能なコードを生成する場合は、Inport ブロックと Outport ブロックが既定で集約された構造体に表示されるように設定します。モデル コンフィギュレーション パラメーター [ルートレベル I/O を以下として渡す][個々の引数] 以外の値に設定します。

    • Inport ブロックおよび Outport ブロックをリアルタイム モデル データ構造体にパッケージ化するには、[モデル データ構造体の一部] を選択します。コード ジェネレーターは、リアルタイム モデル データ構造体が示す既定の I/O 構造体にブロックを集約します。1 つ以上の集約されたエントリポイント関数は、リアルタイム モデル データ構造体を 1 つの引数として受け入れます。この設定を選択すると、関数の引数の数は最小になります。

    • Inport ブロックをある構造体に集約して、Outport ブロックを別の構造体に集約するには、[構造体参照] を選択します。1 つ以上の生成されたエントリポイント関数は、各構造体のアドレスを引数として受け入れます。別の引数でリアルタイム モデル データ構造体を受け入れます。この設定を選択すると、入力と出力は関数インターフェイスでさらに識別しやすくなります。

      この設定では、ルートレベルの Inport ブロックまたはルートレベルの Outport ブロックを削除すると、関数シグネチャが変わる可能性があります。同様に、ルートレベルの Inport ブロックまたは Outport ブロックを、このようなブロックをもたないモデルに追加すると、シグネチャが変わる場合があります。

    • 構造体の特性の制御を強化する場合は、[ルートレベル I/O を以下として渡す][モデル データ構造体の一部] に設定します。次に、Inport ブロックと Outport ブロックの既定のストレージ クラスを、作成した構造化されたストレージ クラスに設定します。この手法では、以下を実行できます。

      • ブロックに対して 1 つの構造体を作成するか、2 つの個別の構造体を作成できます。

      • 構造体型の名前を制御できます。

      • 構造体は、リアルタイム モデル データ構造体のサブ構造体として表示されます。[ルートレベル I/O を以下として渡す][モデル データ構造体の一部] に設定しなければなりません。

      Embedded Coder ディクショナリを使用してストレージ クラスを作成します (Define Service Interfaces, Storage Classes, Memory Sections, and Function Templates for Software Architecture (Embedded Coder)を参照)。コード マッピング エディターを使用してストレージ クラスを適用します (Configure Default Code Generation for Data (Embedded Coder)を参照)。

    詳細については、ルートレベル I/O を以下として渡す (Embedded Coder)を参照してください。

引数のデータ型の制御

引数を使ってデータを交換するように生成されたエントリポイント関数を設定できます。スカラーまたは配列の引数の場合、データのプリミティブ型の名前を制御するには、Simulink.AliasType オブジェクトを使用して、対応するブロックのデータ型を設定するか、モデル全体のデータ型置換を構成します。この手法には Embedded Coder が必要です。詳細については、Control Data Type Names in Generated Code (Embedded Coder)を参照してください。

インターフェイスへのデータ項目のプロモート

既定では、コード ジェネレーターは、モデルのルート レベルにある Inport ブロックおよび Outport ブロックはモデルのデータ インターフェイスを構成すると想定しています。任意の信号、ブロック パラメーターまたはブロック状態をインターフェイスにプロモートして、その他のシステムおよびコンポーネントがアクセスできるようにします。インターフェイスへの内部データのプロモートを参照してください。

関連するトピック