このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
レガシ コード ツールによって外部コードへの呼び出しを生成コードにインポート
レガシ コード ツールとコード生成
Simulink® レガシ コード ツールを使用して、レガシまたはカスタム コード用の完全インライン化 C MEX S-Function を生成できます。S-Function はデバイス ドライバーやルックアップ テーブルのような組み込みコンポーネント用に最適化され、既存の C 関数または C++ 関数を呼び出します。
メモ
レガシ コード ツールは、C++ 関数とインターフェイスで接続することができますが、C++ オブジェクトとは接続できません。ツールが C++ オブジェクトのインターフェイスとして機能するようにこの問題を回避するには、Legacy Code Tool Limitationsを参照してください。
このツールは以下の目的で使用できます。
生成された 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
フィールドで、複数のヘッダー ファイルを指定する場合
レガシ関数へのコード スタイル設定の適用
コード スタイルのモデル コンフィギュレーション パラメーターをレガシ関数に適用するには、次の手順を実行します。
レガシ コード ツールのデータ構造体を初期化します。以下に例を示します。
def = legacy_code('initialize');
データ構造体で、
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 が依存するヘッダー、ソースおよびインクルード ファイル
これらの配布ファイルを使用するときは、次のようにします。
Simulink モデルで配布されたファイルを使用する前に、S-Function ファイルを格納するフォルダーを MATLAB® パスに追加。
レガシ コード ツール データ構造体によって、絶対パスやファイル変更の位置として必須ファイルが登録される場合は、
sFunction
_makecfg.m
またはrtwmakecfg.m
ファイルを再び生成。
外部 C++ オブジェクトの統合
レガシ コード ツールは、C++ 関数とインターフェイスで接続することができますが、C++ オブジェクトとは接続できません。前の例を開始点として使用し、この制限を回避する方法の例を示します。
新しいファイル
adder_cpp.hpp
でadder
のクラス定義を変更します。新しい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<adder*>(*(work1))) #define adderOutput(work1, u1) \ (static_cast<adder*> ((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)';