Main Content

コード生成の概念

TLC は一般的なプログラミング言語であるターゲット言語を解釈し、そのようなものとして使用できます。ただし、TLC は model.rtw ファイルを生成コードに変換するという 1 つの目的のために設計されたものであることに留意してください。そのため、ターゲット言語には、そのタスクに便利な機能は多数用意されていますが、C や C++ などの他の言語で提供されている機能の一部は提供されていません。

ここでは、TLC 内で使用される基本的な構成要素について理解するのに役立つ一般的なプログラミング例をいくつか示します。

出力ストリーム

ターゲット言語の簡単な例として、典型的な "Hello World" の例について考えてみます。hello.tlc という名前のファイルに次のように入力します。

%selectfile STDOUT 
Hello, World

この TLC プログラムを実行するには、次のように入力します。

tlc hello.tlc

これは MATLAB® プロンプトで行います。

この簡単なスクリプトは、TLC の目的 (つまりは設計) の基となるいくつかの重要な概念を示しています。主要な目的はコードを生成することであるため、TLC は出力 (またはストリーム) 指向です。そのため、テキストのバッファーの扱いが簡単で、それらを簡単に出力できます。上記のスクリプトの %selectfile 命令は、TLC で生成されるか認識されないあらゆる後続のテキストを標準の出力デバイスに送信するように TLC に指示しています。TLC で認識される構文は % 文字で始まります。Hello, World は認識されないため、出力にそのまま送信されます。出力先をファイルに簡単に変更できます。STDOUT ストリームは開かないでください。代わりに、コマンド ウィンドウに書き込むように選択します。

%openfile foo = "foo.txt"  
%openfile bar = "bar.txt" 
%selectfile foo 
This line is in foo. 
%selectfile STDOUT 
Line has been output to foo. 
%selectfile bar 
This line is in bar. 
%selectfile NULL_FILE 
This line will not show up anywhere. 
%selectfile STDOUT 
About to close bar. 
%closefile bar 
%closefile foo

バッファーを切り替えてステータス メッセージを表示できます。3 つの命令 %openfile%selectfile、および %closefile のセマンティクスについては、Target Language Compiler Directivesで説明しています。

変数の型

もう 1 つの特徴として、TLC には変数の明示的な型宣言がありません。変数の暗黙的なデータ型の詳細については、Target Language Compilerを参照してください。

レコード

model.rtw ファイルからのコード生成に最も関連する構成要素の 1 つにレコードがあります。"レコード" は、C の構造体や Pascal のレコードに似ています。レコードの宣言の構文は次のとおりです。

%createrecord recVar { ... 	
   field1		value1  ...
   field2		value2 ...
 	 ... 	
  fieldN		valueN ... 
}

ここで、recVar は宣言するレコードの名前、fieldi は文字列、valuei は対応する TLC の値です。

レコード内に入れ子になったレコード (下位レコード) を含めることができます。model.rtw ファイルは、本質的には、複数のレベルの下位レコードを含む CompiledModel という名前の 1 つの大きなレコードです。

MATLAB とは異なり、TLC では同じターゲット ファイル内にない関数定義は明示的に読み込む必要があります。MATLAB では、A = myfunc(B) の行により、myfunc という名前の MATLAB ファイルまたは MEX ファイルが MATLAB で自動的に検索されて読み込まれます。TLC では、%addincludepath 命令を使用して、関数を定義するファイルを明確に含める必要があります。

TLC には、レコードを使用する際に便利な %with 命令が用意されています。Target Language Compiler Directivesを参照してください。

メモ

model.rtw ファイルのフォーマットや構造は、コード ジェネレーターのリリースごとに変更になる可能性があります。

ファイルから読み取ったレコードは、プログラムで宣言する他のレコードと同様に変更が可能です。レコード CompiledModel は、コード生成中に何度も変更されます。CompiledModelmodel.rtw ファイルにあるグローバル レコードです。NumNonvirtSubsystemsNumBlocks など、コード生成に使用される変数が格納されます。また、コード生成中に、多くの新しい変数、オプション、下位レコードが追加されていきます。

LibGetFormattedBlockPath などの関数は、matlabroot/rtw/c/tlc/lib/*.tlc (開く) にある TLC ライブラリで提供されています。使用可能な関数の完全な一覧については、Target Language Compilerの「TLC 関数ライブラリ リファレンス」を参照してください。

レコードのフィールドへの値の代入

レコードのフィールドに値を代入するには、"修飾子付き変数式" を使用する必要があります。修飾子付き変数式では、次のいずれかの形式で変数を参照します。

  • 識別子

  • 修飾子付き変数の後に "." に続けて識別子を指定した次のような形式

    var[2].b
  • 修飾子付き変数の後にかっこで囲んで式を指定した次のような形式

    var[expr]

レコードのエイリアス

TLC では、レコードに対する "エイリアス" を作成できます。エイリアスは、C の構造体へのポインターに似ています。単一のレコードに対して複数のエイリアスを作成できます。エイリアスされたレコードに対する変更は、エイリアスを保持するすべての場所で認識されます。

次のコード フラグメントは、エイリアスの使用法を示しています。

%createrecord foo { field 1 }
%createrecord a { } 
%createrecord b { } 
%createrecord c { }  

%addtorecord a foo foo 
%addtorecord b foo foo 
%addtorecord c foo { field 1 }  

%% notice we are not changing field through a or b. 
%assign foo.field  = 2  

ISALIAS(a.foo) = %<ISALIAS(a.foo)>
ISALIAS(b.foo) = %<ISALIAS(b.foo)>
ISALIAS(c.foo) = %<ISALIAS(c.foo)>

a.foo.field = %<a.foo.field>
b.foo.field = %<b.foo.field> 
c.foo.field = %<c.foo.field> 
%% note that c.foo.field is unchanged

このスクリプトを record_alias.tlc として保存し、次のように呼び出します。

tlc -v record_alias.tlc

次の出力が生成されます。

ISALIAS(a.foo) = 1
ISALIAS(b.foo) = 1
ISALIAS(c.foo) = 0

a.foo.field = 2
b.foo.field = 2 
c.foo.field = 1 

関数の内部では、その関数内にあるローカルで作成したレコードに対するエイリアスを作成できます。次の例に示すように、関数からエイリアスが返されると、関数の終了後も有効なままになります。

%function func(value) Output   
  %createrecord foo { field value }
  %createrecord a { foo foo }
ISALIAS(a.foo) = %<ISALIAS(a.foo)>
   %return a.foo
 %endfunction

 %assign x = func(2)
 ISALIAS(x) = %<ISALIAS(x)>
 x = %<x>
 x.field = %<x.field>

このスクリプトを alias_func.tlc として保存し、次のように呼び出します。

tlc -v alias_func.tlc

次の出力が生成されます。

ISALIAS(a.foo) = 1 
ISALIAS(x) = 1
x = { field 2 } 
x.field = 2

レコードにエイリアスによる何らかの参照がある限り、そのレコードは削除されません。そのため、レコードは関数からの戻り値として使用できます。

関連するトピック