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プログラミングテクニック | このブログの読者になる | 更新情報をチェックする

オブジェクトの入出力(ストリームの利用)

バイト単位の入出力ではなく、より抽象度の高い入出力を実現するために、C++ではストリーム演算子が提供されています。Series60でも同様のストリーム演算子が提供されており、Unicode文字列の入出力などはこのストリームを用いたほうがより簡単に行うことができます。

 このストリームを用いた入出力はRFsクラスを用いてRWriteStream とRReadStreamを作成することで実現できます(特に、書き出す対象がファイルの場合はRFileWriteStream およびRFileReadStreamになります)。

Unicode文字列のストリームを用いた出力

 ここでは、先のサンプルのコードを書き換え、Unicode文字列の入出力が可能なサンプルを見て行きたいと思います(FileTest2.zip)。

 ファイルへの書き出しは次のようになっています。

void CFileTestDocument::WriteFile()
{
RFs& rfs = CCoeEnv::Static()->FsSession();
// ファイルサーバへのセッションを取り出し
RFileWriteStream wStream ;
TInt rst = wStream.Create( rfs,
_L("c:\\temp\\test.txt"), EFileWrite | EFileStreamText );
if( rst == KErrAlreadyExists ){
wStream.Open( rfs,
_L("c:\\temp\\test.txt"), EFileWrite | EFileStreamText );
}

_LIT( KOutputText , "こんにちは" );
wStream << KOutputText ; // ストリームを使っての書き出し
wStream.Close();
}

 先ほどのサンプル(FileTest1.zip)との相違は、RFileを用いるのではなく、RfileWriteStreamを用いているのが一点、次に、

WStream << KOutputText ; // ストリームを使っての書き出し

と、ストリーム演算子(<<)を用いている点。最後に_LIT8マクロではなく、Unicode文字列を生成する_LITマクロを使用している点です。ファイルの読み込みも同様に行っていますので、CFileTestDocument::ReadFile()関数をご参照ください。

ストリーム演算子とExternalizeLとInternalizeL関数

 FileTest2.zipでは、Unicode文字列の読み込みと書き込みを行いました。これに対して、プログラマ作成の任意のオブジェクトをストリーム演算子を用いて書き出す場合、内部的には(C++のテンプレートを用いて)ExternalizeLとInternalizeLの関数を呼び出します。

 つまり、wStream をRWriteStream のインスタンスとすれば、

WStream << someObj;

と、

SomeObj.ExternalizeL( wStream );

は同じ挙動をします。

 ですので、プログラマ作成の任意のオブジェクトに対して、ストリーム演算子を利用したいときは、ExternalizeL関数とInternalizeL関数を用意します。

 もう一点注意が必要な点として、ストリーム演算子が呼び出すExternalizeL関数とInternalizeL関数は最後に「L」がついていることからわかるとおり、リーブを発生します。ですから、ストリーム演算子はリーブを発生する可能性がある点に注意してください。

 組み込みのデータ型に関しては、ストリーム演算子はストリーム演算子のインスタンスがもつ以下のメンバ関数を順次呼び出します。

TInt8 WriteInt8L() ReadInt8L()
TInt16 WriteInt16L() ReadInt16L()
TInt32 WriteInt32L() ReadInt32L()
TUint8 WriteUint8L() ReadUint8L()
TUint16 WriteUint16L() ReadUint16L()
TUint32 WriteUint32L() ReadUint32L()
TReal32 WriteReal32L() ReadReal32L()
TReal64 WriteReal64L() ReadReal64L()

 ここで注意が必要なのが、TInt 型です。TInt型は次のようにtypedef されていますので、データサイズは実行環境に依存します。

typedef signed int TInt;

 ですから、TInt に関してはWriteInt32L() やReadInt32L() などを用いる必要があります。

ファイル入出力を使用する際にリンクするライブラリ

 今回はファイル入出力を用いたサンプルを提供しましたが、ご自身でスクラッチからプログラムを書く場合は、リンクするライブラリを追加する必要があります。そのため、プロジェクトの設定ファイルを変更する必要があります。

 追加が必要なライブラリの例としては、RFileクラスを使用する場合、実装はefsrv.libにあります。また、ファイルへのストリームを使う場合はestor.libに実装が提供されています。

 これらのライブラリはプロジェクトの設定ファイルであるMMPファイルにて、指定する必要があります。具体的には今回お配りしたサンプル(FileTest2.zip)ではFileTest.mmpにて、次のようにestore.libの指定がなされています。ご確認ください。

LIBRARY eikcoctl.lib avkon.lib estor.lib
posted by シンビアン at 16:41| Comment(0) | TrackBack(0) | Series60プログラミングテクニック | このブログの読者になる | 更新情報をチェックする

CDirクラスとRFileクラス

CDirクラスとRFileクラス

 CDir クラスはディレクトリを、RFileクラスはファイルを表すクラスとなっています。ディレクトリの操作や、ファイルに対する操作はおのおのCDirクラスやRFileクラスを用いて行います。ここでRFileクラスを用いた簡単なサンプルを見てみましょう(FileTest.zip)。

 このアプリケーションを実行するには、これまでと同様にビルドして、その後に以下のアイコンを探して下さい(画面1)。


 これを実行すると次のような画面が現れます(画面2)。


 [オプション]から[ファイルテスト]を選んでいただきますと、「hello world」という文字をファイルに書き込み、その書き込んだファイルから文字を取り出して出力します(画面3)。


 それでは、このサンプルの重要な部分を見ていきましょう。まずは、ファイルへの書き出しの部分です。

#include
void CFileTestDocument::WriteFile()
{
// ファイルサーバへのセッションを取り出し
RFs& rfs = CCoeEnv::Static()->FsSession();
RFile file ;
TInt rst = file.Create( rfs,
_L("c:\\temp\\test.txt"), EFileWrite | EFileStreamText );
if( rst == KErrAlreadyExists ){
file.Open( rfs,
_L("c:\\temp\\test.txt"), EFileWrite | EFileStreamText );
}
_LIT8( KOutputText , "hello world" );
file.Write(KOutputText, 11 ) ;
file.Close();

}

 ファイルの指定の部分ですが、

"c:\\temp\\test.txt"

この部分で指定しています。筆者の環境で新たにできているはずのtext.txtを探すと、

\Symbian\8.0a\S60_2nd_FP2_J\epoc32\wins\c\temp

にファイルが存在します。エミュレータ上で実行すると、新たにファイルができているはずですので、探してみてください。

補足:筆者の環境では\Symbian\8.0a\S60_2nd_FP2_J\epoc32\winsがエミュレータ上でのファイルシステムのルートになっております。

 ここで、「Series60では、Unicode を基本的に用いる」という話を思い出してください。通常_LITマクロを使用すると、Unicodeで処理がされますが、ここでは明示的に_LIT8マクロを用いて、ASCII文字列を作成しています。

_LIT8( KOutputText , "hello world" );

 ファイルの読み込みも逆の順序で行っています。次にファイル読み込みの関数を見てみましょう。

HBufC8* CFileTestDocument::ReadFile()
{
// ファイルサーバへのセッションを取り出し
RFs& rfs = CCoeEnv::Static()->FsSession();
RFile file ;
HBufC8* buf = HBufC8::NewL(128);
TPtr8 ptr = buf->Des();
TRAPD( error ,
User::LeaveIfError(
file.Open( rfs,
_L("c:\\temp\\test.txt"), EFileRead | EFileStreamText ) ); );
if( error != KErrNone ){
User::Leave(error);
}
TRAP( error ,
User::LeaveIfError( file.Read( ptr, 128) ); );
if( error != KErrNone ){
User::Leave( error );
}
file.Close();
return buf ;
}

 ここでは、ヒープディスクリプタ(HBufC8)を宣言し、そこにファイルから読み取った内容を書き込んでいます。特に、HBubC8からTPtr8を取り出している点に注意してください。ディスクリプタについては後で説明します。

上記サンプルの注意点

このサンプルではRFileクラスを用いてASCII文字列の入出力を行いました。通常Series60では文字列はUnicodeなのですが、 RFileクラスが持っているReadやWriteなどのメンバ関数はバイト単位の入出力しかサポートしておりません。なので、本来はバイナリデータの入出力でこれらの関数を使うことが多いと思いますが、今回はサンプルのわかりやすさから文字列の入出力を行っています。
posted by シンビアン at 16:35| Comment(0) | TrackBack(0) | Series60プログラミングテクニック | このブログの読者になる | 更新情報をチェックする

Symbian(Series 60)上でのC++によるアプリケーション開発

Symbian OS上の代表的なAPIを用いて、Series 60上でアプリケーションを構築する際に必要な知識を習得します。
実際にSeries 60対応の携帯端末を使った環境で演習を実施します。
Symbianとは、Series60上での開発とはを効率よく学べる3日間です。
本コースはNokia(ノキア)社の認定トレーニングコースです。

期間

3日

時間

10:00〜17:00

定価

\189,000

前提条件

●C++で開発経験がある方
対象者

●Symbian OSおよびSeries 60上でのアプリケーション開発に興味をお持ちの方
 
コース内容

●SymbianとSeries 60
●Series 60 SDK
●Simbian OSの基本
●メモリ管理
●ディスクリプタ
●アプリケーション構造の概要
●リソースファイルとローカライズファイル
●UIコントロール
●クライアント/サーバフレームワーク
●アクティブオブジェクトフレームワーク
●Series 60 UI概要
●グラフィックス
●データ永続性
posted by シンビアン at 16:34| Comment(0) | TrackBack(0) | Symbian OS C++ 実践開発技法 | このブログの読者になる | 更新情報をチェックする

ファイル入出力とディスクリプタ

アプリケーションを作成する場合、どうしてもファイルアクセスは必須の項目になります。今回はまず、簡単にSeries60上でのファイルアクセスを見ていきます。また、ファイルの入出力ではどうしてもデータの格納先になるデータ領域が必要です。 Series60ではデータ領域をディスクリプタとして抽象化することが可能です。ディスクリプタは今回の後半で見て行きます。
ファイルサーバ

 ファイル入出力の話をする前に、ファイルサーバの話をする必要があります。これまでも述べたとおり、Symbian OSはマイクロカーネルを採用しています。したがって、OSが提供すべきサービスの多くはサービスを代行するサーバアプリケーションによって担われます。

RFsクラス

 ファイル関連の操作の場合、ファイルサーバへのクライアント側の窓口はRFsクラスになります。このRFsクラスを用いて以下の操作を行います。

1. ファイルサーバへのセッションを確立する。
2. ファイルサーバへ、ファイル関連の要求をRFsクラスを通して行う。
3. 必要がなくなった時点でセッションを閉じる

 ファイルサーバへのセッションを確立するには、一般に次のようなコードを用います。

RFs fsSession;
// ファイルサーバへのセッションを確立
User::LeaveIfError(fsSession.Connect());
// ここで何らかの処理を行う。
fsSession.Close(); // 不必要になった時点でセッションを閉じる

 また、ファイルサーバへのセッションが残っている間にリーブが発生すると、セッションを閉じないままアプリケーションが終了する可能性があります。そこで、RFsクラスのインスタンスをクリーンアップスタックに積む必要がありますので、その時は、

CleanupClosePushL(fsSession);

とすれば、リーブ発生時にdeleteされる前にClose関数もあわせてコールされます。さらに、クリーンアップスタックからのポップとオブジェクト自体の削除を行いたければ、

CleanupStack::PopAndDestroy();

を呼び出すことで可能です。PopAndDestroyを呼び出すことで、セッションのCloseもあわせて行われます。

 また通常のアプリケーションであれば、上記の様に明示的にファイルサーバへのセッションを作成することなく、アプリケーション実行環境が用意しているデフォルトのセッションがあります。リソースの使用量などから、特に理由が無い限りはこのデフォルトのセッションを使うことをお勧めします。デフォルトのセッションは、

RFs &fs = CCoeEnv::Static()->FsSession();

と、することで取得できます。

 FRsクラスが提供する機能としては、主に以下のものがあります。

1. ファイルを表すRFileクラス、およびディレクトリを表すCDirクラスのインスタンスの取得
2. ディレクトリの作成や、ファイルおよびディレクトリの削除などの機能

posted by シンビアン at 16:31| Comment(0) | TrackBack(0) | Series60プログラミングテクニック | このブログの読者になる | 更新情報をチェックする

非同期の処理

アクティブオブジェクトによる非同期イベントの待機

 次に、メニューの[タイマーのスタート]を選択することにより、アクティブオブジェクトが非同期(ここでは1秒おき)にイベントを受け取ります。そのため、非同期イベントの発生源となるタイマを設定しますが、これはCActiveTest::After()関数で行われます。

void CActiveTest::After(){
iIsRunning = ETrue;
iTimer.After(iStatus, 1000000); // タイマのスタート
SetActive();
//このアクティブオブジェクトがスケジューリングの対象であることを示す
}

 ここで注目していただきたい点として、2点挙げます。

 まず1点目は、iTimer.After関数の第一引数に渡されるiStatusメンバです。このiStatusメンバはCActiveクラスで定義されているもので、非同期のイベントの完了を表すフラグです。iTimer.After関数は第二引数で指定した時間が経過すると、このiStatusの値をKErrNone(つまりKrequestPending以外の値)に設定します。先に述べたアクティブスケジューラの挙動とあわせて確認してください。

 2点目としては、この関数の一番最後に呼び出されているSetActive()関数です。この関数も、アクティブスケジューラに対して自身が非同期のイベントの通知を待っていることを表すために用います。

非同期イベントの通知

 タイマで設定した時間が過ぎ、エラーが発生していなければ、先に登録したアクティブオブジェクトのRunLの関数が呼び出されます。今回は(大まかですが)1秒置きにこのRunL関数が呼び出されますので、このRunL関数でラベルの書き換えを行っています。

void CActiveTest::RunL()
{
After();
sec ++ ;
if( sec >= 60 ){
sec = 0 ;
min ++ ;
}
if( min >= 60 ){
min = 0 ;
hour ++ ;
}
TBuf<32> text;
_LIT(KTime, "Time %d[h]%d[m]%d[s]");
text.Format(KTime, hour, min, sec );
label->SetTextL(text);
iContainer->DrawNow();
}

 ここで、CactiveTest::After()関数を呼び出しているのは、繰り返し1秒後にタイマから通知を受ける必要があるからです。

非同期のイベント待機のキャンセル

 イベント待機のキャンセルが行われた時の処理は、DoCancel関数に記述します。ここでは、RTimerクラスを用いて1秒置きのイベントを受け取っていますので、このリソースクラスに対してタイマのキャンセルをする必要があります。

void CActiveTest::DoCancel()
{
iTimer.Cancel();
iIsRunning = EFalse;
sec = min = hour = 0 ;
label->SetTextL(_L("タイマ停止"));
}

 また、CActiveクラスのデストラクタの中ではCansel関数を呼び出していますが、この関数はそのままDoCancel関数を呼び出します。

CActiveTest::~CActiveTest()
{
Cancel();
iTimer.Close();
}

最後に

 今回は、アクティブスケジューラとアクティブオブジェクトの二つを見ていきました。特にアクティブオブジェクトはコーディング量も若干多くなると思います。今回は処理ロジックをそのままRunL関数に書き込みましたが、再利用を考えると、何らかのコールバックを登録、RunLで登録したコールバックを呼び出せば汎用性が上がると思います。次回はファイル入出力について見ていく予定です。
posted by シンビアン at 13:55| Comment(0) | TrackBack(0) | Series60プログラミングテクニック | このブログの読者になる | 更新情報をチェックする

アクティブオブジェクトを用いたタイムカウンタアプリケーションのサンプル

それでは、アクティブオブジェクトと用いたサンプルとして、簡単なタイムカウンタのアプリケーションを見ていきましょう。このサンプルプログラムは、並行処理が必要なプログラムとなっています。バックエンドではタイマーの処理を、フロントエンドではユーザーからの操作を受け付けています。[activetest.zip]

 今回のサンプルも、前回以前と同様にダウンロードしてビルドしますと、次のようなアイコンが追加されます(画面1)。


 このアプリケーションを起動し、次に[オプション]から[タイマーのスタート]を選択すると、下図のような画面が現れて1秒ごとに時間経過をカウントしていきます(画面2)。


 さらに、[オプション]から[タイマーの停止]を選択すると次のような画面になり、タイマを停止します(画面3)。


 先ほども述べたとおり、Series60ではマルチスレッドのアプリケーションは推奨されていません。今回のサンプルでは、この1秒おきの通知をアクティブオブジェクトで受け取り、スレッドはあくまでも一本になります。

アクティブオブジェクトの作成と登録まで

 次に、アクティブオブジェクトの作成と登録までを見ていきましょう。先ほど述べた通り、アクティブオブジェクトは必ずCActiveクラスを継承して作成されます。今回のサンプルでは、アクティブオブジェクトとなるクラスは次のように宣言されたCactiveTestクラスになります。

class CActiveTest:public CActive
{
public:
CActiveTest(); // コンストラクタ
~CActiveTest(); // デストラクタ
void ConstructL(CEikLabel* ,
CActiveTestContainer*); // 第二フェーズコンストラクタ
void After(); // タイマー開始関数
TBool IsRunning();
void RunL(); // コールバックの関数
void DoCancel(); // キャンセル時に呼び出される関数
protected: // data
// RTimerのインスタンス
RTimer iTimer;
CEikLabel* label ; // 時間を表示するラベル
/// 以下省略
};

 このCActiveクラスのコンストラクタにおいて、このアクティブオブジェクトの優先度の設定とアクティブスケジューラへの登録が行われています。

CActiveTest::CActiveTest():
CActive(EPriorityStandard)
// EPriorityStandard は優先度が通常のものであることを表す。
{
// 中略
CActiveScheduler::Add(this);
// 自分自身をアクティブスケジューラに追加
}

 先ほども述べたとおり、アクティブスケジューラへの登録はCActiveScheduler::Add関数で行われます。
posted by シンビアン at 13:48| Comment(0) | TrackBack(0) | Series60プログラミングテクニック | このブログの読者になる | 更新情報をチェックする

非同期の処理

アクティブスケジューラ

 続いてアクティブスケジューラを見ていきましょう。アプリケーション起動時にフレームワークは、アクティブスケジューラを作成します。また、アクティブスケジューラにアクティブオブジェクトを登録するには、CActiveSchedulerクラスのstatic void Add(CActive* anActive)関数を用います。

 アクティブスケジューラはループで実現されていますが、このループの中では大まかに次の処理がなされています。

1. 登録されているアクティブオブジェクトのうち、優先度上位のものから順番に次の条件を満たすことを確認する。

(1) … CActive::IsActive()がETrueを返す。このことで登録されたアクティブオブジェクトが未処理の非同期イベントの通知を待っていることを表す。
(2) … 上記で待っている非同期のイベントが終了していることを表すフラグであるCActive::iStatusの値がKRequestPending以外の値になっている。

2. 1.で調べた条件を満たすアクティブオブジェクトのRunLの関数を呼び出し、その実行終了を待つ

3. 1.に戻る

 アクティブスケジューラは、キーイベントなどのユーザー入力も処理している点にも注意する必要があります。つまり、アクティブスケジューラが呼び出す関数RunL()は、速やかに終了する必要があるわけです。仮にRunLの関数の実行に数秒かかる場合、アプリケーションは、その数秒間ユーザーの入力を受け付けなくなり、ハングしたように見えます。

補足:本稿では説明しませんが、自作のアクティブスケジューラを作成することも可能です。

アクティブオブジェクト

 上記のアクティブスケジューラの説明で見たとおり、アクティブオブジェクトのRunL関数により、非同期のイベントの通知を受けます。また、RunL以外にもiStatusなどの重要なメンバが存在します。これらのメンバはCActiveクラスで定義されており、新たにアクティブオブジェクトを作成する際には、必ずこのCActiveクラスを継承する必要があります。以下にCActiveクラスの重要なメンバとその説明を大まかに記述します。

* RunL():非同期のイベントが終了した際、コールバックとして呼ばれる関数。
* DoCancel():非同期のイベントの待機がキャンセルされたときに呼び出される関数。
* Cancel():オーバーロードしない限りはDoCancel関数を呼び出す。
* RunError(TInt):RunLがリーブした際、例外処理の関数として呼ばれる。
* SetActice():このアクティブオブジェクトが非同期のイベントの通知を待っている状態に設定する関数。
* CActive(TInt aPriority):コンストラクタ。引数にはこのアクティブオブジェクトの優先度を設定する。
* TRequestStatus iStatus :非同期のイベントの状態を表すフラグ。このフラグがKrequestPendingの時は非同期のイベントが完了していないことを表す。

posted by シンビアン at 13:46| Comment(0) | TrackBack(0) | Series60プログラミングテクニック | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

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