2006年02月15日

ディスクリプタについて

今回のサンプルでは、複数箇所でディスクリプタを使用しています。以降ではこのディスクリプタについて見て生きたいと思います。ディスクリプタとは、Series60の中では、以下の代用として使用されます。

* NULLで終わる文字列
* バイト配列
* バイトポインタ

 今回のサンプル(FileTest.zipとFileTest2.zip)でもファイルから文字列を読み込んでくる箇所で、文字列を格納する領域としてディスクリプタを使用しています。具体的には、CFileTestDocument::ReadFile()関数の中では以下の箇所になります。 HBufCやTPtr などがディスクリプタになります。

HBufC* buf = HBufC::NewL(128);
TPtr ptr = buf->Des();
// 中略….
rStream >> ptr ;

 ディスクリプタの種類には以下の5種類があります。

* 抽象ディスクリプタ(TDes TDesC)
* リテラルディスクリプタ(TLitC)
* バッファディスクリプタ(TBuf, TBufC)
* ヒープディスクリプタ(HBuf)
* ポインタディスクリプタ(TPtr TPtrC)

 リテラルディスクリプタは特殊になりますが、ディスクリプタは配列やポインタをカプセル化した「スマートポインタ」と考えてくださればよいかと思います。つまり、ディスクリプタの保持する領域と、領域に関する情報(確保した領域や、現在の使用量など)をカプセル化しているものです。バッファディスクリプタとポインタディスクリプタの相違は、配列をカプセル化するか、それともポインタの指す領域をカプセル化するかになります。

 そして、バッファディスクリプタ、ポインタディスクリプタ双方とも「あるメモリ上の領域に対するアクセスの方法と、領域の情報を保持している」点は変わりません。そこで(オブジェクト指向で一般に行われるように)抽象的なディスクリプタのクラスを考えることができます。これが抽象ディスクリプタになるわけです。

 ここで、ディスクリプタ関連のクラスの階層関係を見ておきましょう(図1)。

■ 図1 8ビットディスクリプタクラスの派生 (出典:NRIラーニングネットワーク 「ノキア Series 60 C++開発入門コース」より)

 上記は8ビットのディスクリプタ(つまり保存されるデータのサイズがバイト単位となる)のクラス階層を示しています。通常は文字データの格納を考え、単にTDesCのクラスを使用したときは16ビットのディスクリプタとなるようにtypedefがなされています。16ビットのディスクリプタも同一のクラス階層を持っています。

 また、クラス名に「C」がついているものは変更用の操作が提供されず、単にデータの参照のみができます。これに対して、クラス名に「C」が付かないものはデータを参照する操作と変更する操作が提供されます。

 それでは、次にバッファディスクリプタとポインタディスクリプタ、ヒープディスクリプタの3つをもう少し見ていきましょう。

TBufCとTBuf(バッファディスクリプタ)

 TBufとTBufCは「配列の領域をカプセル化したディスクリプタである」とご理解ください。データ構造(16ビットのディスクリプタ)は下図のようになります(図2)。

■ 図2 メモリの構成図 (出典:NRIラーニングネットワーク 「ノキア Series 60 C++開発入門コース」より)

TPtrとTPtrC(ポインタディスクリプタ)

 バッファディスクリプタが配列をカプセル化しているのに対して、ポインタディスクリプタはポインタで指される領域をカプセル化します(図3)。

■ 図3 メモリの構成図 (TPtrC8) (出典:NRIラーニングネットワーク 「ノキア Series 60 C++開発入門コース」より)

HBufC (ヒープディスクリプタ)

 ヒープディスクリプタはヒープ上に確保した領域をカプセル化したディスクリプタです(図4)。

■ 図4 メモリの構成図 (出典:NRIラーニングネットワーク 「ノキア Series 60 C++開発入門コース」より)

 ヒープディスクリプタは若干特殊で、変更可能なディスクリプタであるHBufは存在しません。その代わり、HBufC::Des()関数で変更可能なポインタディスクリプタを取得することができます。

再度、今回のコードの断片を

 それでは、今回のサンプルで登場したコードの断片をもう一度見てみましょう。

HBufC* buf = HBufC::NewL(128);
TPtr ptr = buf->Des();
// 中略….
rStream >> ptr ;

 ここの流れは以下のようになってます。

1. ヒープディスクリプタ(128文字分、バイト数では256バイト)を確保し
2. 1で作成したディスクリプタからDes関数を用いて変更可能なポインタディスクリプタを作成し(当然、このポインタディスクリプタがカプセル化する領域と、ヒープディスクリプタがカプセル化する領域は同一)
3. ストリーム演算子を用いてポインタディスクリプタに対してデータを代入する

今回の終わりに当たって

 今回は簡単なファイルアクセスの方法とディスクリプタについて触れました。今回は触れませんでしたが、Series60は組み込みデータベースを持っています。アプリケーションの種類によってはデータベースアクセスを行った方が開発効率が良い場合もあるでしょう。アプリケーションの種類に応じて適宜用いてください。

 また、紙面の関係からSeries60が提供するより先進的なストアやストリームネットワーク、さらにスイズル(Swizzle)については割愛しました。複雑なファイル構造や大きなファイルの読み込みを行うときは、これらの技術項目をあたってみてください。

 後半のディスクリプタについては、若干慣れない部分があるかと思います。しかし、慣れてしまえば簡単ですので、いろいろサンプルをご自身で書いてみることをお勧めします。次回はグラフィックスの処理について解説する予定です。
posted by シンビアン at 16:50| Comment(0) | TrackBack(0) | Series60プログラミングテクニック | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/13321477

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。