基本的な C MEX S-Function の作成と実装
このトピックでは、基本的な C MEX S-Function (システム関数) を作成する方法、C MEX S-Function と Simulink® の相互作用、および C MEX S-Function を作成して Simulink モデルに実装する簡単な例について説明します。
S-Function は、Simulink 環境の機能を拡張する強力なメカニズムを提供します。"S-Function" は MATLAB®、C、C++ または Fortran で記述された Simulink ブロックをコンピューター言語で記述したものです。C、C++、または Fortran で記述されたブロックには、C MEX S-Function を使用します。C、C++、および Fortran® S-Function は、mex ユーティリティを使用して MEX ファイルとしてコンパイルされます (C MEX 関数のビルドを参照)。他の MEX ファイルと同様に、S-Function は、MATLAB 実行エンジンが自動的に読み込んで実行できる、動的にリンクされたサブルーチンです。
C MEX S-Function の作成方法
C MEX S-Function は、次のいずれかの方法を使用して作成できます。
手書きの S-Function — C MEX S-Function を最初から記述できます。(基本的な C MEX S-Function の作成と実装で、詳しい手順の例を示します。)独自の S-Function を作成するための開始点として使用できる C MEX S-Function の完全なスケルトン実装については、Templates for C S-Functionsを参照してください。手書きの S-Function では最も広範な機能がサポートされますが、記述が難しい場合があります。
S-Function Builder — このブロックは C/C++ コードを統合し、グラフィカル ユーザー インターフェイスを使用して指定した仕様およびコード フラグメントから C MEX S-Function をビルドします。これにより、S-Function を最初から記述する必要がなくなります。S-Function Builder ブロックを使用すると、C MEX S-Function を記述するタスクが簡略化されますが、サポートされる機能は少なくなります。S-Function Builder ブロックの詳細については、Use a Bus with S-Function Builder to Create an S-Functionを参照してください。
Simulink Coder™ — Simulink Coder 製品には、グラフィカル サブシステムから C MEX S-Function を生成する方法が用意されています。C MEX S-Function をはじめて記述する場合は、Simulink サブシステム内にアプリケーションの一部を作成し、S-Function ターゲットを使ってサブシステムを S-Function に変換できます。生成されたファイルからは、特定のブロックを S-Function 内でどのように実装できるかに関する情報が得られます。S-Function ターゲットの使用方法の詳細と制限については、モデルまたはサブシステムの S-Function ターゲットの使用 (Simulink Coder)を参照してください。Simulink エンジンと相互作用する API を使用して、外部コードを表現する S-Function を開発できます。コード ジェネレーターでこの S-Function を使用し、コードを生成します。コード生成における異なるタイプの S-Function の詳細については、S-Function とコード生成 (Simulink Coder)を参照してください。
C MEX S-Function を記述する各方法の特徴と制限の詳細については、Available S-Function Implementationsを参照してください。
C MEX S-Function と Simulink の相互作用
C MEX S-Function は、シミュレーション中にその関数に関する情報を Simulink エンジンに提供する必要があります。シミュレーションの進行中に、エンジン、ODE ソルバー、および C MEX S-Function は連携して特定のタスクを実行します。このようなタスクには、初期条件とブロックの特性の定義や、微分、離散状態、出力の計算などがあります。
MATLAB S-Function と同様に、Simulink エンジンは、S-Function が実現するコールバック メソッドを呼び出すことで C MEX S-Function と相互作用します。各メソッドは、S-Function によって機能が定義されているブロックのシミュレーションに必要となる、ブロック出力の計算などの事前定義されたタスクを実行します。ただし、S-Function は、S-Function が実現する機能に応じて各メソッドのタスクを自由に実行できます。たとえば、mdlOutputs メソッドは、現在のシミュレーション時間におけるブロック出力を計算する必要があります。ただし、S-Function は、その関数に適した任意の方法でこれらの出力を計算できます。このコールバックベースの API を使用すると、S-Function を作成できるため、目的に応じた機能のカスタム ブロックを作成することもできます。
C MEX S-Function が実装できるコールバック メソッドのセットは、MATLAB S-Function で使用可能なコールバック メソッドを上回っています。S-Function API のごく一部のコールバック メソッドについては、実装するために C MEX S-Function が必要になります。ブロックで行列信号などの特定の機能を実装しない場合は、機能の実装に必要なコールバック メソッドを自由に省略できます。このため、簡単なブロックを極めて短時間で作成できます。
C MEX S-Function の一般的な形式を以下に示します。
#define S_FUNCTION_NAME /* your_sfunction_name_here */ #define S_FUNCTION_LEVEL 2 #include "simstruc.h" static void mdlInitializeSizes(SimStruct *S) { } /* <additional S-function routines/code> */ static void mdlTerminate(SimStruct *S) { } #ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else #include "cg_sfun.h" /* Code generation registration function */ #endif
mdlInitializeSizes は、Simulink エンジンが S-Function と相互作用する際に最初に呼び出すルーチンです。その後、エンジンは他の S-Function メソッド (すべて mdl で始まる) を呼び出します。シミュレーションの最後に、エンジンは mdlTerminate を呼び出します。
基本的な C MEX S-Function の例の紹介
このセクションでは、簡単な C S-Function を作成するためのモデルとして使用できる C MEX S-Function の例を紹介します。サンプル S-Function timestwo.c は、入力を 2 倍にして出力します。
次のモデルでは、timestwo S-Function を使用して正弦波の振幅を 2 倍にし、スコープにプロットします。

S-Function のブロック ダイアログ ボックスでは、S-Function 名として timestwo が指定されており、パラメーター フィールドは空です。
timestwo S-Function には、次の図に示す S-Function コールバック メソッドが含まれています。S-Function の最後に、Simulink/Simulink Coder インターフェイスに記載されているコードの抜粋を含めます。

timestwo.c の内容を以下に示します。コードの説明は、この例の後に記載しています。
#define S_FUNCTION_NAME timestwo #define S_FUNCTION_LEVEL 2 #include "simstruc.h"
static void mdlInitializeSizes(SimStruct *S) { ssSetNumSFcnParams(S, 0); if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) { return; /* Parameter mismatch reported by the Simulink engine*/ } if (!ssSetNumInputPorts(S, 1)) return; ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED); ssSetInputPortDirectFeedThrough(S, 0, 1); if (!ssSetNumOutputPorts(S,1)) return; ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED); ssSetNumSampleTimes(S, 1); /* Take care when specifying exception free code - see sfuntmpl.doc */ ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE); }
static void mdlInitializeSampleTimes(SimStruct *S) { ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); }
static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
int_T width = ssGetOutputPortWidth(S,0);
for (i=0; i<width; i++) {
*y++ = 2.0 *(*uPtrs[i]);
}
}
static void mdlTerminate(SimStruct *S){}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else #include "cg_sfun.h" /* Code generation registration function */ #endif
この例は次の 3 つの部分で構成されています。
定義とインクルード
コールバック メソッドの実装
Simulink (または Simulink Coder) 製品インターフェイス
定義とインクルード
この例は、次の define ステートメントから始まります。
#define S_FUNCTION_NAME timestwo #define S_FUNCTION_LEVEL 2
最初の define ステートメントは、S-Function の名前 (timestwo) を指定します。2 番目の define ステートメントは、S-Function が "レベル 2" の形式であることを指定します (レベル 1 とレベル 2 の S-Function の詳細については、Convert Level-1 C MEX S-Functionsを参照してください)。
これら 2 つの項目を定義した後、この例では simstruc.h をインクルードします。これは、SimStruct データ構造体と MATLAB アプリケーション プログラム インターフェイス (API) 関数にアクセスできるようにするヘッダー ファイルです。
#define S_FUNCTION_NAME timestwo #define S_FUNCTION_LEVEL 2 #include "simstruc.h"
simstruc.h ファイルは、Simulink エンジンが S-Function に関する情報を保持するために使用する SimStruct というデータ構造体を定義します。また、simstruc.h ファイルは、MEX ファイルが SimStruct に対する値 (ブロックの入力信号と出力信号など) の設定と取得を実行できるようにするマクロも定義します (About SimStruct Functionsを参照)。
コールバック メソッドの実装
timestwo S-Function の次の部分には、必須のコールバック メソッドの実装が含まれます。
mdlInitializeSizes
Simulink エンジンは mdlInitializeSizes を呼び出して、S-Function に必要な入力端子と出力端子の数、端子のサイズ、その他の情報 (状態数など) について調べます。
mdlInitializeSizes の timestwo 実装では、次のサイズ情報が指定されています。
0 個のパラメーター
そのため、[S-Function ブロック パラメーター] ダイアログ ボックスの [S-Function パラメーター] フィールドは空でなければなりません。パラメーターが含まれている場合は、エンジンによってパラメーターの不一致が報告されます。
1 つの入力端子と 1 つの出力端子
入力端子と出力端子の幅は、サイズが動的に変化するように設定されています。これにより、S-Function が任意の幅の入力信号を受け入れることができるとエンジンに伝えられます。既定では、サイズが動的に変化する入力端子と出力端子の幅は、S-Function の入力端子と出力端子が 1 つだけの場合に等しくなります。
1 つのサンプル時間
mdlInitializeSampleTimesコールバック メソッドは、サンプル時間の実際の値を指定します。例外のないコード
例外のないコードを指定すると、S-Function の実行が高速化されます。このオプションを指定する際は、注意が必要です。一般に、S-Function が MATLAB 環境と相互作用していない場合は、このオプションを問題なく指定できます。詳細については、Simulink Engine Interaction with C S-Functionsを参照してください。
mdlInitializeSampleTimes
Simulink エンジンは mdlInitializeSampleTimes を呼び出して、S-Function のサンプル時間を設定します。timestwo ブロックは、駆動ブロックが実行されるたびに実行されます。そのため、単一の継承サンプル時間 INHERITED_SAMPLE_TIME をもちます。
mdlOutputs
エンジンは各タイム ステップで mdlOutputs を呼び出して、ブロック出力を計算します。mdlOutputs の timestwo 実装では、入力信号に 2 が乗算され、出力に解が書き込まれます。
以下の行
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
は、入力信号にアクセスします。ssGetInputPortRealSignalPtrs マクロはポインターのベクトルを返します。このベクトルには以下を使用してアクセスする "必要" があります。
*uPtrs[i]
入力信号へのアクセスの詳細については、Accessing Signals Using Pointersを参照してください。
次の行:
real_T *y = ssGetOutputPortRealSignal(S,0);
は、出力信号にアクセスします。ssGetOutputPortRealSignal マクロは、ブロック出力を含む配列へのポインターを返します。
次の行:
int_T width = ssGetOutputPortWidth(S,0);
は、ブロックを通過する信号の幅を取得します。S-Function は、入力をループ処理して出力を計算します。
mdlTerminate
エンジンは mdlTerminate を呼び出して、S-Function がシミュレーションの最後にタスクを実行できるようにします。これは必須の S-Function ルーチンです。timestwo S-Function は終了アクションを実行しないため、このルーチンは空です。
Simulink/Simulink Coder インターフェイス
S-Function の最後に次のコードを含めて、S-Function を Simulink 製品または Simulink Coder 製品に接続します。
#ifdef MATLAB_MEX_FILE #include "simulink.c" #else #include "cg_sfun.h" #endif
このトレーラーは、すべての S-Function の末尾に必要です。省略した場合、S-Function をコンパイルしようとすると、failure during build of exports file というエラー メッセージが表示されて中止されます。
timestwo サンプルのビルド
この S-Function をコンパイルするには、コマンド ラインで
mex timestwo.c
と入力します。mex コマンドは、既定のコンパイラを使用して timestwo.c ファイルをコンパイルし、リンクします。mex コマンドは、Simulink ソフトウェアで使用するための、動的な読み込みができる実行可能ファイルを作成します。複数の MATLAB 対応コンパイラがある場合は、mex -setup コマンドを使用して既定を変更できます。既定のコンパイラの変更とサポートされるコンパイラのリストを参照してください。
結果として得られる実行可能ファイルは MEX S-Function と呼ばれます。ここで、MEX は "MATLAB Executable" の略です。MEX ファイルの拡張子はプラットフォームごとに異なります。たとえば、32 ビットの Microsoft® Windows® システムでは、MEX ファイルの拡張子は .mexw32 です。