C Caller ブロックを使用して Simulink® に新規または既存の C コードを統合できます。Simulink モデルでカスタム ブロックを作成するには、C Caller ブロックによって、外部のソース コードおよびライブラリで指定された外部 C 関数を呼び出すことができます。the C Caller ブロックのメリットには次のものがあります。
単純な C 関数の自動化された統合
Simulink Coverage™、Simulink Test™、および Simulink Design Verifier™ との統合
Simulink Coder™ との統合
The C Caller ブロックにより C アルゴリズムを Simulink に持ち込むことができます。動的システムをモデル化するには、代わりに S-Function Builder を使用します。次のステップでは、C Caller ブロックを使用して Simulink に C コードを統合するワークフローを説明します。
C 関数を含む外部ソース コード ファイルを指定します。
Simulink ツールストリップから [コンフィギュレーション パラメーター] を開きます。
左側のペインで [シミュレーション ターゲット] を選択します。
C Caller ブロックによる解析を有効にするには [カスタム コードのインポート] ボックスがオンになっていることを確認します。
ディレクトリとファイル パスは、絶対パスでもモデル ディレクトリまたは現在の作業ディレクトリへの相対パスでもかまいません。カスタム コードへの相対パスの指定 (Stateflow)を参照してください。
[ヘッダー ファイル] を選択して、ヘッダー ファイルの名前を #include
タグと共に入力します。
[追加のビルド情報] の下で [インクルード ディレクトリ] を選択し、ヘッダー ファイルなどの追加のビルド情報が格納されているフォルダーを入力します。
[ソース ファイル] を選択して、ソース ファイルのパスと名前を入力します。モデルとソース ファイルが異なるディレクトリにある場合、ファイル名の前にソース ファイルが含まれているディレクトリを入力します。
メモ
関数がヘッダー ファイルで宣言されていてソース コードで実装されていない場合、シミュレーションとモデルのコンパイルのために空のスタブ関数が自動的に生成されます。
Simulink で行列データが格納される順序を指定できます。C 関数へ、または C 関数から渡される行列データは、指定した既定の関数配列レイアウトに変換されます。関数配列レイアウトが指定されていない場合、行列データは C Caller を通じて Simulink データと同じ順序で渡され、行優先と列優先の乱れにより計算エラーが発生することがあります。すべての Simulink データについて同じ既定の関数配列レイアウトに従うようにしてください。
列優先 — C Caller ブロックは Simulink データを列優先の順序で処理します。3 行 3 列の行列があるとします。C Caller ブロックでは、この行列は 1 列目、2 列目、3 列目の順序で格納されます。
行優先 — C Caller ブロックは Simulink データを行優先の順序で処理します。3 行 3 列の行列があるとします。C Caller ブロックでは、この行列は 1 行目、2 行目、3 行目の順序で格納されます。
任意 — C Caller ブロックで、列優先および行優先の両方の順序で配列データを格納できます。その結果、列優先および行優先の両方の設定でコードを生成できます。
指定なし — 配列のデータは列優先および行優先の両方の順序で格納できます。[任意] 設定と比較して、列優先設定でのみコードを生成できます。
Simulink での行優先および列優先の配列レイアウトの詳細については、既定の関数配列のレイアウトを参照してください。
[既定の関数配列のレイアウト] の下の配列レイアウト オプションを選択します。
特定の配列レイアウトをコードの関数のいくつかに適用する必要がある場合、[関数別に指定] をクリックしてこれらの関数を選択します。
[適用] をクリックして変更を受け入れます。
[OK] をクリックして [コンフィギュレーション パラメーター] を閉じます。
Simulink キャンバスで C Caller を入力するだけで、Simulink へのカスタム C コード統合を開始できます。または、C Caller ブロックを [ライブラリ ブラウザー] 、 [User-Defined Functions]からドラッグします。ブロックをダブルクリックして [ブロック パラメーター] ダイアログ ボックスを開いて、関数の名前と端子の指定を確認します。
[カスタム コードを更新します。] をクリックしてソース コードとその依存関係をインポートします。
C 関数が [関数名] の下に表示されます。関数の完全なリストが表示されない場合は、 をクリックしてソース コードを再インポートします。
関数宣言を表示する、または関数への入力/出力変数をヘッダー ファイル内で表示するには、[関数宣言に移動します。] をクリックしてソース ファイルを移動します。
ソース ファイルとその依存関係を変更する、または関数配列レイアウトを定義して選択するには、[Custom code settings] をクリックして、[コンフィギュレーション パラメーター] の [シミュレーション ターゲット] タブを開きます。
C
Caller ブロックの [端子仕様] テーブルを使用したり、コマンド ラインで FunctionPortSpecification
オブジェクトを作成したりすることで、C 関数の引数をソース コードから Simulink 端子にマッピングできます。ソース コードで、ヘッダー ファイルには Simulink 端子に接続される C 関数の引数が含まれています。
extern void mean_filter(const unsigned char* src, unsigned char* dst, unsigned int width, unsigned int height, unsigned int filterSize);
[端子仕様] によって、引数の詳細とそれらが Simulink で C Caller ブロックにどのように接続されるかが表示されます。
名前 — 入力および出力引数の名前を指定します。[名前] は、ソース コードからの C 関数で定義されている、関数の引数またはパラメーターの名前です。この列は参照目的でのみ使用されます。
スコープ — C 関数の引数が Simulink のスコープにどのようにマッピングされるかを指定します。引数には関数の定義により既定のスコープがあり、そのスコープをソース コードの関数定義によって変更できます。
Simulink スコープ | スコープからブロックへのマッピング |
---|---|
Input | ブロック入力端子 |
Output | ブロック出力端子 |
InputOutput | ブロックの入力端子と出力端子 |
Global | ブロックで使用されるグローバル変数 |
Parameter | ブロックの調整可能なパラメーター |
Constant | 定数値 |
const double
*u
のような定数の修飾子定義がある場合、引数は Input または Parameter のみです。定数の修飾子がない場合、引数は既定で Output であり、それを Input
、InputOutput
、または Parameter
スコープに変更できます。この場合、C 関数がポインターで示されるメモリを変更しないようにしてください。引数が Output
タイプである場合、このポインターで示される各要素はこの関数の呼び出しのたびに再割り当てされます。
C 引数 | Simulink スコープ |
---|---|
関数の戻り |
|
| Input 、Parameter 、Constant |
|
|
| Output (既定)、InputOutput 、Input 、Parameter |
|
|
[InputOutput]
端子を使用して、C 関数のポインターで渡される入力をマッピングします。[InputOutput]
端子を使用して作成された端子は、入力端子および出力端子と同じ名前になります。[InputOutput]
端子を使用すると、入力端子と出力端子のバッファーの再利用が有効になります。これにより、信号のサイズとブロック レイアウトに応じてメモリの使用量が最適化されます。
C 関数の引数を [InputOutput]
端子にマッピングするには、関数の定義において変数をポインターとして定義します。
extern void mean_filter(unsigned char* src, unsigned int width, unsigned int height, unsigned int filterSize);
次に、[端子仕様] テーブルで InputOutput
スコープに対する端子仕様を選択し、結果として生じる関数出力をカスタム関数の入力変数に代入します。
カスタム コードのグローバル変数を使用して、それらの変数を適切な Simulink スコープにマッピングできます。モデルでのグローバル変数の使用を有効にするには、[モデル設定] 、 [コンフィギュレーション パラメーター] 、 [シミュレーション ターゲット]からカスタム コードのグローバルを関数インターフェイスとして有効にするを選択します。グローバル変数を C Caller ブロックの [Input]
、[Output]
、[InputOutput]
または [Global]
スコープにマッピングできます。これらのスコープの可用性は、カスタム コードのグローバル変数の仕様によって異なります。
[Global]
スコープでは、カスタム コードと C Caller ブロック間でデータを転送でき、ブロックで計算中にグローバル変数を使用できます。[Global]
スコープを使用して転送された値はブロック インターフェイスで表示できません。次の表は、コード例の抜粋とその既定端子および使用可能な端子を示しています。
コード例 | Simulink スコープ |
---|---|
double data; void foo(void) { int temp = data; } | グローバル変数では変数
|
double data; void bar(void) { data = 0; } | データはグローバル変数に書き込まれます。次のスコープが使用できます。
|
double data; void foo2(void) { data = data + 1; } | データはグローバル変数で読み取りと書き込みの両方が実行されます。次のスコープが使用できます。
|
ラベル — Simulink ブロックの対応する引数のラベルを示します。既定では、引数のラベルは、変更しない限り引数名と同じです。
Simulink スコープ | Simulink 端子のラベル |
---|---|
| 端子の名前 |
inputoutput | 入力端子と出力端子両方の端子の名 |
Global | 端子名とグローバル変数名 |
| パラメーター名 |
| 定数値の式。 入力引数の名前のサイズ式。例: |
Type — Simulink データ型と C 関数の引数のデータ型との一致を判別します。
C 引数のデータ型 | Simulink データ型 |
---|---|
符号付き文字 | int8 |
符号なし文字 | uint8 |
char | int8 または uint8 (コンパイラによる) |
int* | int32 |
符号なし整数* | uint32 |
short * | int16 |
long * | int32 または fixdt(1,64,0) (オペレーティング システムによる) |
float | single |
double | double |
int8_t* | int8 |
uint8_t* | int8 |
int16_t* | int16 |
uint16_t* | uint16 |
int32_t* | int32 |
uint32_t* | uint32 |
typedef struct {…} AStruct** | Bus:AStruct |
typedef enum {..} AnEnum** | Enum:AnEnum |
* C Caller が整数型を取る場合 (例: int16_t)、一致する基本データ型の固定小数点型 (例: fixdt(1, 16, 3)) に変更できます。 ** C Caller 同期ボタンによって、C 関数によって使用される構造体または列挙型を Simulink バスおよび列挙型としてインポートできます。 |
サイズ — 引数のデータの次元を指定します。
C 引数の次元 | Simulink 端子の次元 |
---|---|
| スカラー (1) |
| 継承 (-1) (既定) 引数が出力端子用の場合、サイズを指定する必要があります。出力端子のサイズは継承できません。 |
| 継承 (-1) (既定)
グローバル変数の場合、サイズはスカラー (1) です。 |
| サイズは [2, 3]。 |
FunctionPortSpecification
オブジェクトの作成と C Caller ブロック プロパティの編集[端子仕様] テーブル プロパティをプログラムで変更するには、FunctionPortSpecification
オブジェクトを作成して、そのプロパティを変更します。モデル内の選択された C
Caller ブロック用に FunctionPortSpecification
オブジェクトを作成するには、コマンド ラインに次を入力します。
myCCallerConfigObj = get_param(gcb, 'FunctionPortSpecification')
myCCallerConfigObj = FunctionPortSpecification with properties: CPrototype: 'real_T add(real_T u1, real_T u2);' InputArguments: [1×2 Simulink.CustomCode.FunctionArgument] ReturnArgument: [1×1 Simulink.CustomCode.FunctionArgument] GlobalArguments: [1×0 Simulink.CustomCode.FunctionArgument]
CPrototype
プロパティは読み取り専用であり、C 関数の入力変数の宣言を示します。InputArgument
プロパティと ReturnArgument
プロパティによって作成される FunctionArgument
オブジェクトは、上記の [端子仕様] テーブル用に定義されたルールに従って、そのプロパティをさらに編集することができます。詳細については、FunctionPortSpecification
を参照してください。C Caller ブロックでグローバル引数を変更するには、getGlobalArg
を使用して GlobalArguments
オブジェクトへのハンドルを作成し、そのプロパティを修正します。
ライブラリ モデルを作成して C Caller ブロックをグループ化し、モデルを整理した状態に維持できます。
新しいライブラリ モデルを開きます。[シミュレーション] タブで、[新規] 、 [ライブラリ] を選択します。
[モデル化] タブの [設計] で、[シミュレーションのカスタム コード] をクリックします。
コードによって [言語] オプションで C
または C++
を選択し、[カスタム コードのインポート] ボックスがオンになっていることを確認します。
ソース コードと依存関係の指定 の説明に従ってソース ファイルとその依存関係を追加します。
C Caller ブロックを作成して C 関数を呼び出します。
ライブラリ モデルから Simulink モデルにブロックを挿入するには、単純にブロックをモデルにドラッグします。
外部のデバッガーを MATLAB® プロセスに追加し、外部 C コードをデバッグするには、次を使用してデバッグ シンボルを生成します。
Simulink.CustomCode.debugSymbols('on')
次を使用して、この設定をオフにします。
Simulink.CustomCode.debugSymbols('off')
グローバル変数 — 関数の入出力としてのグローバル変数は、多次元配列をサポートしません。
カスタム コード設定の初期化/終了 — カスタム コードにメモリを割り当てたり割り当て解除したりする必要がある場合、メモリの割り当てと割り当て解除は、カスタム コード設定の [初期化関数] および [終了関数] フィールドに挿入します。
複素数データのサポート — C Caller ブロックは Simulink の複素数データ型をサポートしません。
連続サンプル時間 — C Caller ブロックは連続サンプル時間をサポートしません。
可変引数 — C の可変引数はサポートされません (たとえば、int sprintf(char *str, const char *format,
...)
)。
C++ 構文 — C Caller ブロックはネイティブの C++ 構文を直接サポートしません。C++ コードとインターフェイスする C 関数ラッパーを記述する必要があります。
C Caller ブロックを含むモデルをテストする場合は、Test Integrated C Code (Simulink Test)を参照してください。
C Caller | FunctionPortSpecification
| getGlobalArg
| legacy_code | MATLAB Function | MATLAB System | S-Function | S-Function Builder