本資料で利用する用語について補足します。
用語の解説は、規格などで定められる定義に沿っていない場合があります。
ソフトウェア開発環境
TWELITE無線マイコンのソフトウェア開発用のSDKをTWELITE SDK (またはMWSDK)と呼称します。
TWELITE無線モジュールが利用する無線規格です。MWXライブラリを使用する限り、無線規格の詳細を意識する必要はありません。
無線通信における最小の通信単位です。
最大量は通信方式や通信時の設定によって変わりますが、MWXライブラリ標準の通信<NWK_SIMPLE>では、ユーザが1パケットで送信できるデータ量は90バイトです。
「貨物」といった意味合いですが、無線パケットに含まれるデータ本体のことをいいます。
「点・節」といった意味合いですが、無線ネットワーク内の無線局のことを言います。
本ライブラリを用いて作成したプログラム。そのソースコードまたは動作するプログラムのことを言います。
アクトの中でも特にイベント形式のプログラム。そのソースコードまたは動作するプログラムのことを言います。
ビヘイビアは1つのクラス定義による記述で、TWENETからのコールバック関数やイベントや割り込み処理を記述しひとまとめにしています。MWXライブラリでは以下の3種類のビヘイビアがあります。
アプリケーションビヘイビア:イベントドリブンでのアプリケーション記述を行い、ユーザが定義するクラス。
ボードビヘイビア:TWELITE無線モジュールを実装するボードの機能利用を簡素化するためのクラス。
ネットワークビヘイビア:無線ネットワークの手続きを簡素化するためのクラス。
ビヘイビア名は < >
で括って表記します。例えばシンプル中継ネットワークのビヘイビア名は <NWK_SIMPLE>
です。
本ライブラリの解説では、ライブラリで最初からグローバル宣言されたオブジェクトをクラスオブジェクトと呼称します。Serial
, Wire
などです。これらクラスオブジェクトは手続きなしまたは開始手続きを行うことで利用できます。
メモリを比較的多く消費するクラスオブジェクトは、初期化手続きの際(.setup()
または.begin()
メソッド)に初期化パラメータに沿ったメモリを確保します。
一般の用語です。C言語の知識を前提に解説します。
C++言語のこと。
MWXライブラリはC++とC言語によって記述されています。
C++規格のバージョンの一つ。2011年式のC++といった意味合いで、2011年にISOで規格化されています。直前のC++03から大きく機能拡張されています。C++14, C++17といったより新しいバージョンがあります。
MWXライブラリはC++11で追加された機能や構文を用いて実装されています。MWSDKのコンパイラ対応はC++11までとなります。
あるデータに注目して、その手続きをひとまとめにしたもの。構造体に、その構造体を取り扱うための手続きが含まれています。実際にはもっと深い話題に発展しますが、専門書を参考にしてください。
C++においては、キーワードの struct
と class
は本質的には同じもので、いずれのキーワードで宣言してもクラスとなります。
上記のクラス定義をC言語でも行った場合、例えば以下のようになります。
既存のC言語のライブラリやその内部の構造体などをクラスに包含し、C++特有の機能性を追加するなどして、利用の便を図ったものです。解説中でも「~構造体をラップした」といった記述をする場合があります。
MWXライブラリは、TWENETのCライブラリのラッパークラスと、新たに実装したクラス群との組み合わせになっています。
クラスに定義される関数で、クラスに紐付いています。
クラスを実体化(メモリ確保)したもの。
本解説ではオブジェクトとインスタンスは同じ意味合いとして取り扱っています。
オブジェクト生成時の初期化手続き。
コンストラクタと対になってオブジェクトが破棄されるときの手続きです。
C++では仮想クラスによりポリモーフィズム(多態性)を実現します。具体的にはvirtual
キーワードで指定た純粋仮想関数を定義したクラスです。
MWXライブラリでは、コンパイラの制限や性能上の理由で仮想関数を使用しません。ポリモーフィズムを実現するのに別の手法を用いています。
C/C++言語では { }
で括った範囲と考えてください。この中で生成したオブジェクトは、スコープから出るときに破棄されます。この時デストラクタが呼び出されます。
以下は、明示的にスコープを設定したものです。helo2
は8行目まで実行された時点で破棄され、デストラクタが呼び出されます。
MWXライブラリでは以下のような記法を用いています。ここではif文の条件判定式内で宣言(C89といった旧いC言語ではこういった場所での宣言はできません)されたオブジェクトの有効期間は、if文の{}
内になります。
例えば二線シリアルバスなど、開始と終了の手続きがあって、その間だけオブジェクトによってバスを操作するような手続きです。オブジェクトの生成後、バスの接続が適切であればif文のtrue節が実行され、生成したオブジェクトによってバスの書き込みまたは読み出しを行います。バスの読み書き操作が終了したらif文を脱出し、この時デストラクタが呼び出され、バスの利用終了手続きが行われます。
定義名の重複を避けるためC++では名前空間が積極的に用いられます。名前空間にある定義にアクセスするには::
を用います。
テンプレートはC言語のマクロを拡張したものと考えてください。
この例では、簡単な配列を定義しています。T
とN
はテンプレートのパラメータで、T
は型名をN
は数値を指定し、T
型で要素数N
の配列クラスを定義しています。
C++11ではNULLポインタをnullptr
と記述するようになりました。
C++では、参照型を利用できます。これはポインタによるアクセスに似ていますが、必ずオブジェクトを参照しなければならないという制約があります。
以下のような参照渡しのパラメータを持つ関数ではi
の値をincr()
内で書き換えることが出来ます。
テンプレートの解説例ですがoperator[]
の戻り型をT&
に変更しています。こうすることでa[0]=1
のように配列内部のデータに対して直接代入操作ができるようになります。
MWXライブラリのプログラミングインタフェースは、原則といてポインタ型の利用をせず、参照型を用いています。
C++11 では型推論のauto
キーワードが導入されています。これはコンパイラが初期化の記述からそのオブジェクトの型を推論するため、具体的な型名の記述を省略できます。これはtemplateを用いたクラス名が非常に長くなるような場合に効果的です。
解説中では多くの場合ユニバーサル参照と呼ばれるauto&&
を用いています。ユニバーサル参照については、ここでは参照渡しの場合も意識せずに記述できるものと考えてください。
配列など特定のデータ型のオブジェクトを複数個格納するためのクラスをコンテナと呼びます。テンプレートの例で挙げたmyary
のような配列クラスもコンテナと呼んでいます。
MWXライブラリでは、配列クラスsmplbuf
とFIFOキュークラスsmplque
を用意しています。
C言語で言うところのポインタ(もちろんC++でも同じようにポインタは使えます)を拡張した概念です。C言語のポインタは、メモリが連続した要素を先頭から末尾まで連続的にアクセスする手段と考えることが出来ます。FIFOキューを考えてみます。もっとも単純なキューの実装はリングバッファによるものですが、メモリーの連続性はありません。こういったデータ構造であっても、イテレータを用いるとポインタと同じように記述できます。
イテレータを取得するため.begin()
,.end()
のメソッドが用いられます。コンテナの先頭を指すイテレータを.begin()
で取得します。末尾の次を指すイテレータを.end()
で取得します。末尾ではなく、末尾の次である理由にはforやwhile文のループ記述の明快さ、コンテナに格納される要素数が0の場合の取り扱いが挙げられます。
上記では、que
の各要素について、イテレータp
を用いて各要素にsome_process()
を適用しています。p
は++
演算子によって次の要素を指すイテレータとしてインクリメントしています。本来ポインタでは記述できないデータ構造を持つコンテナであっても、このようにポインタを用いた処理と同じような処理が出来ます。
.end()
が末尾の次を示すため、while文の終了判定は(p != e)
のように簡潔です。キューに要素がない場合は.begin()
は.end()
と同じイテレータを返します。(何も格納されていない要素のイテレータの次ですから、最初に格納すべき領域を示すイテレータと考えればよいでしょう)
メモリ上で連続したコンテナの場合、通常、そのイテレータは通常のポインタとなります。その操作時に大きなオーバーヘッドにはならないことが期待できます。
C++の標準ライブラリにはSTL(Standard Template Library)が含まれます。MWXライブラリでの一部を利用しています。
TWELITE向けのC/C++コンパイラの制約から、利用できる機能はごく一部です。
例えば最大や最小値を求めるといった処理をC言語では型に応じて別々に記述していました。こういったコードは型の部分だけ違って他は同じといったものも少なくありません。C++ではtemplateやイテレータなどを用いて、こういった処理を型に依存せず記述することができます。これをアルゴリズムと呼んでいます。
例えば上記のように最大値を求めるアルゴリズムです。このアルゴリズムは型に依存しません。(ジェネリックプログラミングと呼ばれます)
ここではque
のイテレータを指定し、その最大と最小を得るアルゴリズムstd::minmax_elenet
を適用しています。std::minmax_elemet
はC++標準ライブラリ内に定義されています。その戻り値は任意の2つの値を組み合わせるstd::pair
です。このアルゴリズムは、イテレータの示す要素同士で<,>,==
といった演算子での比較が出来れば最大と最小を計算してくれます。戻り型もイテレータの型から導かれます。