Main Content

レガシ コード ツールによって外部コードへの呼び出しを生成コードにインポート

レガシ コード ツールとコード生成

金宝app®レガシ コード ツールを使用して、レガシまたはカスタム コード用の完全インライン化 C MEX S-Function を生成できます。S-Function はデバイス ドライバーやルックアップ テーブルのような組み込みコンポーネント用に最適化され、既存の C 関数または C++ 関数を呼び出します。

メモ

レガシ コード ツールは、C++ 関数とインターフェイスで接続することができますが、C++ オブジェクトとは接続できません。ツールが C++ オブジェクトのインターフェイスとして機能するようにこの問題を回避するには、遗留代码工具的局限性を参照してください。

このツールは以下の目的で使用できます。

  • 生成された S-Function をシミュレーション向けにコンパイルし、ビルドする。

  • 既存の外部コードを呼び出すように設定されたマスク付きの S-Function ブロックを生成する。

コードを生成しようとしているモデルにこのような S-Function を含めるには、ツールを使用して TLC ブロック ファイルを生成します。TLC ブロック ファイルは、モデルの生成コードが既存の C または C++ 関数を呼び出す方法を指定します。

S-Function の依存するファイルのフォルダーが、S-Function を動的に読み込める実行可能ファイルの含まれるフォルダーではない場合、ツールを使用して S-Function にsFunction_makecfg.mまたはrtwmakecfg.mファイルを生成します。ファイルを生成することで、S-Function を含むモデルを作成するときにそれらの依存関係が維持されます。たとえば、カスタム ターゲットなどいくつかの用途では、ファイルをターゲット特有の場所に配置する可能性もあります。ビルド プロセスは、S-Function が動的に読み込める実行可能ファイルと同じフォルダーにあるsFunction_makecfg.mまたはrtwmakecfg.mを探して、そのファイル内の関数を呼び出します。

詳細については、Integrate C Functions Using Legacy Code Toolを参照してください。

コード生成のためのインライン化 S-Function ファイルの生成

S-Function を使用するモデルのコードを生成するには、お使いのアプリケーションのコード生成要件に応じて、次のいずれかを実行します。

  • インライン化 S-Function に 1 つの.cppファイルを生成する。レガシコードツールのデータ構造体で,既存のC関数からS-Function ソース ファイルを生成する前に、Options.singleCPPMexFileフィールドの値をtrueに設定する。以下に例を示します。

    def.Options.singleCPPMexFile = true; legacy_code('sfcn_cmex_generate', def);

  • インライン化 S-Function にソース ファイルと TLC ブロック ファイルを生成する。以下に例を示します。

    def.Options.singleCPPMexFile = false; legacy_code('sfcn_cmex_generate', def); legacy_code('sfcn_tlc_generate', def);

singleCPPMexFile の制約

以下の場合は、singleCPPMexFileフィールドをtrueに設定できません。

  • Options.language='C++'

  • 次の Simulink オブジェクトのいずれかを使用して、IsAliasプロパティをtrueに設定する場合

    • Simulink.Bus

    • Simulink.AliasType

    • Simulink.NumericType

  • レガシ コード ツールの関数の仕様で、状態引数としてスカラー作業データを表現するためのvoid*またはvoid**を含む場合

  • レガシ コード ツール構造体のHeaderFilesフィールドで、複数のヘッダー ファイルを指定する場合

レガシ関数へのコード スタイル設定の適用

コード スタイルのモデル コンフィギュレーション パラメーターをレガシ関数に適用するには、次の手順を実行します。

  1. レガシ コード ツールのデータ構造体を初期化します。以下に例を示します。

    def = legacy_code('initialize');
  2. データ構造体で、Options.singleCPPMexFileフィールドの値をtrueに設定します。次に例を示します。

    def.Options.singleCPPMexFile = true;

設定を確認するには、次を入力します。

def.Options.singleCPPMexFile

singleCPPMexFile の制約

以下の場合は、singleCPPMexFileフィールドをtrueに設定できません。

  • Options.language='C++'

  • 次の Simulink オブジェクトのいずれかを使用して、IsAliasプロパティをtrueに設定する場合

    • Simulink.Bus

    • Simulink.AliasType

    • Simulink.NumericType

  • レガシ コード ツールの関数の仕様で、状態引数としてスカラー作業データを表現するためのvoid*またはvoid**を含む場合

  • レガシ コード ツール構造体のHeaderFilesフィールドで、複数のヘッダー ファイルを指定する場合

異なる場所にあるファイルの依存関係への対処

既定の設定では、レガシ コード ツールは、S-Function が依存するファイルは、動的に読み込むことができる、その S-Function の実行可能ファイルと同じフォルダー内に存在していると仮定します。S-Function がそれ以外の場所にあるファイルに依存しており、テンプレート makefile ビルド プロセスを使用する場合は、その S-Function についてsFunction_makecfg.mまたはrtwmakecfg.mファイルを生成します。たとえば、レガシ コード ツール データ構造体がパス名としてコンパイルのリソースを定義するような場合に、このファイルを生成します。

sFunction_makecfg.mまたはrtwmakecfg.mファイルを生成するには、'sfcn_makecfg_generate'または'rtwmakecfg_generate'を最初の引数とし、レガシ コード ツール データ構造体の名前を 2 番目の引数として、関数legacy_codeを呼び出します。以下に例を示します。

legacy_code('sfcn_makecfg_generate', lct_spec);

同じフォルダー内の複数の登録ファイルを使用して、関数legacy_codeの単一の呼び出しでファイルごとに S-Function を生成する場合は、'sfcn_makecfg_generate'または'rtwmakecfg_generate'を指定する関数legacy_codeの呼び出しがすべての登録ファイルに共通していなければなりません。詳細については、Handling Multiple Registration Filesを参照してください。

たとえば、レガシ コード ツール構造体の配列としてdefsを定義する場合は、'sfcn_makecfg_generate'で関数legacy_codeを 1 回呼び出します。

defs = [defs1(:);defs2(:);defs3(:)]; legacy_code('sfcn_makecfg_generate', defs);

詳細については、S-Function のビルド サポートを参照してください。

シミュレーションおよびコード生成のための S-Function の配布

レガシ コード ツールで S-Function を生成し、それを他のユーザーに配布することができます。シミュレーションやコードを生成するために S-Function を配布するには、次のファイルを共有します。

  • 登録ファイル

  • 動的な読み込みができるコンパイル済みの実行可能ファイル

  • TLC ブロック ファイル

  • sFunction_makecfg.mまたはrtwmakecfg.mファイル

  • 生成された S-Function が依存するヘッダー、ソースおよびインクルード ファイル

これらの配布ファイルを使用するときは、次のようにします。

  • 金宝app仿真软件モデルで配布されたファイルを使用する前に、S-Function ファイルを格納するフォルダーを MATLAB®パスに追加。

  • レガシ コード ツール データ構造体によって、絶対パスやファイル変更の位置として必須ファイルが登録される場合は、sFunction_makecfg.mまたはrtwmakecfg.mファイルを再び生成。

外部 C++ オブジェクトの統合

レガシ コード ツールは、C++ 関数とインターフェイスで接続することができますが、C++ オブジェクトとは接続できません。前の例を開始点として使用し、この制限を回避する方法の例を示します。

  • 新しいファイルadder_cpp.hppadderのクラス定義を変更します。新しいadderオブジェクトの動的な割り当て、メソッドadd_one()の呼び出し、割り当てられたメモリの解放を行う 3 つの新しいマクロを追加します。それぞれのマクロは、adderオブジェクトへのポインターを受け取ります。レガシ コード ツールによって呼び出される各関数は C 言語のようなシグネチャをもたなければならないため、ポインターはキャッシュされてvoid*として渡されます。その後マクロ内で明示的にadder*にキャストしなければなりません。adderの新しいクラス定義を次に示します。

    #ifndef _ADDER_CPP_ #define _ADDER_CPP_ class adder { private: int int_state; public: adder(): int_state(0) {}; int add_one(int increment); int get_val() {return int_state;}; }; // Method wrappers implemented as macros #define createAdder(work1) \ *(work1) = new adder #define deleteAdder(work1) \ delete(static_cast(*(work1))) #define adderOutput(work1, u1) \ (static_cast ((work1)))->add_one(u1) #endif /* _ADDER_CPP_ */
  • adder_cpp.cppを更新します。クラスの変更に伴い、1 つのグローバルなインスタンスの代わりに、生成された各 S-Function が固有のadderオブジェクトを管理します。

    #include "adder_cpp.hpp" int adder::add_one(int increment) { int_state += increment; return int_state; }
  • 次の変更によってrtwdemo_sfun_adder_cpp.cppを更新します。

    • StartFcnSpecは、新しいadderオブジェクトを割り当ててポインターをキャッシュするマクロを呼び出します。

      def.StartFcnSpec = 'createAdder(void **work1)';
    • OutputFcnSpecは、メソッドadd_one()を呼び出してその S-Function 固有のadderポインター オブジェクトを提供するマクロを呼び出します。

      def.OutputFcnSpec = 'int32 y1 = adderOutput(void *work1, int32 u1)';
    • TerminateFcnSpecは、メモリを解放するマクロを呼び出します。

      def.TerminateFcnSpec = 'deleteAdder(void **work1)';

参考

関連するトピック