Skip to content

Latest commit

 

History

History
293 lines (201 loc) · 17 KB

CDLref_signature.rst

File metadata and controls

293 lines (201 loc) · 17 KB

シグニチャ記述

シグニチャ記述は、シグニチャを定義するものです。 シグニチャとは、コンポーネント間をインタフェースする関数頭部の集合で、呼び口、受け口に対応付けられます。

【記述例】

signature sInputOutput {
   ER  setOutput( [in]int8_t val );       // in 基本指定子
   ER  getInput( [out]int8_t *val );      // out 基本指定子
   ER  noParameter( void );               // 引数なし
};

ここで siganture はキーワードであり、sInputOutput はシグニチャ名です。'{', '}' で囲まれた中に ';' で区切って 0 個以上の関数頭部を列挙します。 慣習として、シグニチャ名は 's' で始めます。

関数の個数が 0 個の場合、コンポーネント間に何らかの関係があるが、実際には関数の呼び出しが行われないことを表します。 リージョン間のスループラグインは適用されません。

シグニチャ記述の指定子

コールバック(callback)指定子

コールバック(callback)指定子は、コールバックに用いられるシグニチャであることを指定します。 コールバック関数を呼び出すための呼び口、受け口に用いられることが意図されていることを表します。

コールバック指定されたシグニチャに対応付けられた受け口から呼び口への、逆結合が可能です。 組上げ記述 (セル記述)の逆結合の侯を参照してください。 通常の結合を用いることもできます。

コンテキスト(context)指定子

コンテキスト(context)指定子は、シグニチャがどのコンテキストで使用されるものかを指定します。 以下のいずれかを指定します。

  • "task" … タスク部
  • "non-task" … 非タスク部
  • "any" … いずれのコンテキストも可能

【記述例】

[context( "task" )]
  signature sSignature {
};

コンテキストが指定されていないシグニチャは、 "task" が指定されたものと仮定されます。

【補足説明】コンテキストの指定は、コンポーネントの設計者、および利用者に対するメモである。TECS ジェネレータは、この記述に基く検査はしない。

逸脱(deviate)指定子

逸脱(deviate)指定子は、関数の引数が、以下の規定に合わない(逸脱)ことを表します。

関数頭部

関数頭部は、C 言語と同様に記述しますが、引数には入出力方向を示する基本指定子を記述する必要があります。

関数に引数がない場合、 void を記述します。

関数頭部の指定子

一方向(oneway)指定子

一方向(oneway)指定子は、呼び元から呼び先へのみ値を渡すことができることを表します。 つまり oneway 指定された関数では、引数に in または send 基本指定子のみ指定することができます。

一方向指定された関数は、非同期実行される可能性があります。 一方向指定された関数が、戻り値を返すことはできますが、非同期実行された場合には、実際には返されません。 戻り値は、非同期実行を実現するコンポーネントから返されます。

一方向指定された関数が非同期実行される場合、in 基本指定子が指定されたポインタ型の引数について、ポインタが指している先の値のコピーが作成され、コピーへのポインタが渡されます。

【補足説明】一方向指定された関数が非同期実行される場合、in 基本指定子が指定されたポインタ型の引数について、コピーが取られるかどうかは、スループラグインの実装にかかっている。 一方向指定された関数を非同期実行させるスループラグインの実装者は、コピーが取られるように設計しなくてはならない。

ポインタ型の引数

ポインタの多重度は、以下のいずれかです。

  • 単一のポインタ
  • 二重ポインタ

ただし、receive 引数の場合は、上記のポインタ型の値を渡すため、もう一重、ポインタの多重度が増えます。

また、二重ポインタ(receive においては三重ポインタ)は、以下のいずれかの場合に用いることができます。

  • size_is と string の両方の指定子をを伴う場合
  • ポインタの指すものが構造体で、size_is が指定されている場合

さらに in 引数の場合、ポインタが指すものの型に const 指定子を付加する必要があります。

ポインタ型の引数が配列(文字列を含む)を指す場合には、ポインタ指定子を指定する必要があります。

引数に void 型のポインタを用いることはできません。

上記の条件を満たさない場合は、逸脱 (deviate) となります。

引数の指定子

基本指定子

基本指定子には、in, out, inout, send, receive があります。

以下の表は、それぞれの基本指定子について、データを渡す方向、非ポインタ型引数の可否、適用可能なポインタの多重度、渡されたメモリ領域を受け取った側がデアロケートする必要の有無を表します。 なお、二重ポインタ (receive においては三重ポインタ)は、ポインタ型の引数の項で示した条件を満たす場合に適用できます。

データを渡す方向 非ポインタ型 ポインタ多重度 デアロケート 備考
in 呼び元→呼び先

単一、二重

不要

ポインタ型の場合 const が必要
out 呼び元←呼び先

不可

単一、二重

不要

ポインタの参照する先のデータを返す
inout 呼び先⇔呼び元

不可

単一、二重

不要

send 呼び元→呼び先

不可

単一、二重

必要

引数としてアロケータシグニチャを取る
receive 呼び元←呼び先

不可

二重、三重

必要

引数としてアロケータシグニチャを取る

C 言語におけるポインタ型がの引数は、以下の点であいまいさがあります。

  • 呼び元から呼び先に値を渡すのか、その逆かが不明
  • ポインタが指す記憶域を、受け取った側が解放する必要があるのか、ないのか、不明
  • ポインタが、非配列を指すのか、配列を指すのか不明、また配列を指す場合、その大きさが不明

TECS CDL では、上記の問題を以下のように克服しています。

  • データを渡す方向を、基本指定子で表す
  • 記憶域の解放の要否は send, receive 基本指定子により表す
  • ポインタが非配列を指すのか、配列を指すのかを、配列を指す場合、その大きさをポインタ指定子により表す

in/out/inout 指定子の、いずれも記憶域は呼び元が準備します。

【記述例】

signature sInOut {
   ER      in( [in,string]char *buf );
                        /* in では、呼び元が文字列を用意する */
   ER      out( [out,string(64)]char *buf );
                        /* out では、呼び元が長さ 64 のバッファを用意する */
   ER      inout( [inout,string(*len)]char *buf, [inout]uint16_t *len );
                        /* inout では、呼び元が長さ len のバッファを用意する */
                        /* *len の出力方向は文字列長さを返す */
};

out 引数で文字列のコピーではなく、文字列へのポインタを返すことは逸脱になります。 例えば、エラーメッセージのような固定の文字列を出力引数で得る場合、以下の例のように逸脱となります。

【記述例】

[deviate]
signature sOutStringPointor {
   ER      getErrorMessage( [out]const char_t **message );
};

send/receive 指定子をしたシグニチャの例を示します。

【記述例】

signature sSendReceive {
   ER      sendMessage( [send(sAlloc),size_is(len)] int8_t *buf, [in]int16_t len );
   ER      receiveMessage( [receive(sAlloc),size_is(len)] int8_t **buf, [out]int16_t len );
};

ポインタ指定子

ポインタ指定子は、ポインタ型の引数に対して用いることができます。 ポインタ指定子には size_is, count_is, string, nullable があります。 ポインタが指すものが非配列の場合、size_is, count_is, string のいずれも指定しません。

size_is:: ポインタは配列を指すことを表すとともに、配列の大きさを引数で表す。

(配列の大きさであり、バイト数ではない) 多重ポインタに指定された場合、パラメータに最も近いポインタの大きさを指定する。 ただし receive においては、パラメータから2番目のポインタに対する指定となる。 size_is は引数を取るが、定数またはパラメータリストに内にある他の引数を含み、整数型を返す式である。 size_is の引数は、呼び元で指定する。receive の場合は呼び先で指定してもよい。 size_is は第二引数をとることができる。第二引数は size_is の最大値を定数で指定する。 セルタイプコードにおいて、size_is の引数値が 0 となる場合、ポインタ値として NULL を渡す。

count_is:: count_is は size_is を補助するもので、配列の有効な要素が含まれる個数(最大添数+1) を表す。

count_is は省略することができる。その場合、size_is で指定された大きさが有効な要素数とみなされる。 count_is は引数を取るが、定数またはパラメータリストに内にある他の引数を含み、整数型を返す式である。 count_is の引数は、ポインタが指す先に値を設定した側が行う。 in, send の場合は、呼び元が指定する。 out, receive の場合は、呼び先が指定する。 inout の場合は、呼び先、呼び元が、それぞれ設定する。

string:: ポインタは文字列を指すことを表す(char 以外の型の場合は、NULL 終端された配列)。

多重ポインタに指定された場合、パラメータから最も遠い (型指定子にもっとも近い) ポインタに対する指定となる。 size_is とともに指定された場合は、文字列へのポインタの配列であることを表す。つまり二重ポインタ (receive の場合は三重ポインタ)となる。 string は引数をとることもできる。引数は、定数またはパラメータないにある他の引数を返す式で、文字列の際だし長さを表す。文字列が最大長さに達する場合は、NULL 終端されていない。 string の引数は、呼び元で指定する。receive の場合は呼び先で指定してもよい。

nullable:: ポインタは NULL を渡すことがあることを示す。

多重ポインタの場合、パラメータに最も近いポインタが NULL を渡すことがあることを示す。 ただし receive の場合は、パラメータから2番目のポインタが NULL を渡すことがあることを示す (recieve 指定されたパラメータとしては NULL を渡すことはできない)。 size_is と nullable を同時に指定することはできない。 この場合、size_is のみを指定し、セルタイプコードにおいて size_is の引数値として 0 を渡す (size_is の項も参照)。

ポインタ指定子をしたシグニチャの例を示します。

【記述例】

signature sInputOutput {
   ER      putMessage( [in,size_is(len)] const int8_t *buf, [in]int16_t len );
   ER      getMessage( [out,size_is(*len),count_is(*len)] int8_t *buf, [inout]int16_t *len );
};

アロケータシグニチャ

アロケータは、メモリを割付けるコンポーネントのことです。 アロケータシグニチャは、アロケータの受け口が持つシグニチャのことです。 アロケータシグニチャは、send または receive 指定子の引き数として用いられます。 アロケータのシグニチャは、少なくとも alloc と dealloc 関数を持つ必要があります。

alloc 関数の第一引数は、アロケートしようとするメモリ領域のサイズ(バイト数;整数型)、または、メモリ領域へのポインタを返すポインタとします(二重ポインタ)。 alloc 関数の第二引数は、第一引数が整数の場合、アロケートされたメモリ領域へのポインタを返すポインタとします(二重ポインタ)。

dealloc 関数の第一引数は、デアロケートしようとするメモリ領域へのポインタとします。

alloc, dealloc が、2つ以上の引数を持つとき、through プラグインによって RPC チャネルを生成させるのに、関数の引数に与えるべき値をプラグイン引数として指定します。 仮引数名によってどの引数に対する値かを識別します。 このため alloc と dealloc で同じ仮引数名が指定されると、これらは同じ値を指定されることになります。 もし、異なる値を指定する必要があるのであれば、シグニチャの設計者は、これらに異なる仮引数名を与える必要があります。 関数の引数に与えるべき値として、定数または他の引数を指定できます。

alloc, dealloc 関数に引き数を追加することができます。 また、アロケータシグニチャに realloc 関数などを追加することもできます。

アロケータシグニチャの事例を以下に示します。 アロケータシグニチャは、alloc 関数において、二重ポインタの使用要件を満たさない、また void 型のポインタため、逸脱 (devaite) となります。

【記述例】

[deviate]
signature sAlloc {
  ER alloc( [in]size_t len, [out]void **p );
  ER dealloc( [in]void *p );
};

シグニチャプラグイン記述

シグニチャプラグイン記述は、シグニチャに対しプラグインを適用することを指示します。

【記述例】

generate( SignaturePluginName, sSignatureName, "option..." );
ここで、それぞれのワードは、以下を意味します。
  • generate はキーワードである
  • SignaturePluginName はシグニチャプラグイン名である
  • sSignatureName はシグニチャプラグインを適用するシグニチャの名前である
  • オプションは、プラグインごとに規定される。文字列リテラルを渡す

シグニチャプラグイン記述は、シグニチャを定義した後で記述します。