次のページ 前のページ 目次へ

3. more予備知識

moreソフトは、イベントドリブン型のプログラムとしてC言語で開発します。 Add inソフトが DOS上のプログラムだとすれば、 moreソフトは Window上のプログラム開発と同様です。 更に、ザウルスOS自体がマルチタスクOSですから、 他のタスクの事も考えて作っていく必要があります。 この章では、イベントドリブン、 そしてmoreソフト特有の事柄について軽く眺めていきましょう。

3.1 言語の違い・実行環境の違い

Add inソフトは BASICで書かれたソフトで、PIザウルス内のBASICインタプリタ上で動作します。 それに対して moreソフトはC言語で書かれており、MIザウルスの上で直接動作します(下図参照)。

Add in ソフト
BASIC インタプリタ more ソフト
PI ZAURUS OS MI ZAURUS OS

Add inソフトはBASICインタプリタの上で動作するので動作スピードも遅くなり、 できる事も制限されます。その代わり、システムに関する事はほとんど考えなくても良く、 エラーが有ってもインタプリタが親切に教えてくれるなど気楽な環境です。 作成途中でもそこそこ実行できる、 むしろ実行しながら作っていけるというのも Add in の作りやすさに一役かっています。

対してmoreソフトの方は、直接動作する為にスピード面でも機能面でも 圧倒的に優位なのですが、それだけにプログラム・ミスがあれば 即暴走となり、ザウルス全体が止まってしまいます。 特にMIシリーズのザウルスは、マルチタスクで1度に複数のソフトが動作してますので、 正しく作らないと他のソフトに迷惑をかけてしまうわけです。 Cの場合、コンパイルして初めて実行形式となる為、 ある程度形を作り上げないと実行できないというのも、 moreの作りにくさ、面倒な点です。

3.2 イベントドリブンな組み方

Add inの場合、他の機能や処理とは直接関わりなく、BASICの世界の中でだけ 泳いでいれば良いものです。従って、画面の描画にしても自分だけを考えていれば良く、 ましてやマルチタスクなど関係ありません。 何かループで入力待ちをするにも、
	while
		キー入力チェック
		if 入力された then ループを抜ける
	endwhile
のように、自分の事だけを考えれば済むことです。 しかし、moreの場合、色々と世話してくれるBASICインタプリタなんてありません。 画面の再描画から何から何まで、全てをルールに従って実行しなくてはなりません。 マルチタスクの絡みもあり、ループで入力待ちをするのは極力避けなければなりませんし、 キー入力だけではなく、数々のユーザー操作、システムイベントを受け付けてあげなくてはなりません。

・・そこで出てくるのがイベントドリブンです。

これはキー入力でもペンタッチでも何でも『イベント』としてシステムから受け取り、 それに基づいて動作するように組むというものです。 こうすることで、キー入力ならキー入力だけではなく、 その他のイベントもいつでも受け取れるようになる上、 イベントを取得する際にシステムに処理をまわす事も可能になります。 つまり、moreソフトは1つのイベント取得&配送のループがあり、 そこからイベントに応じてサブルーチンを呼び出しながら動作するわけです。

イベントドリブン図
[イベント配送ループの概略サンプル]

	MESSAGE	Message;
	BOOLEAN	endflg = false;

	while( ! endflg ) {
		GetEvent( &Message );			/* イベントを取得 */

		switch( Message.CommonMsg.MessageID ) {	/* イベントに応じた処理へ振り分け */
		case ペンタッチ:
			ペンタッチの処理();
			break;
		case キー入力:
			キー入力の処理();
			break;
		case 再描画:
			画面再描画の処理();
			break;
		case その他:
			その他の処理();
			break;
		case 終了要求
			endflg = true;
			break;
		}
	}
moreソフトは大体このようなイメージで、 具体的には画面上のボタンが押されたならばその処理を実行する・・・ といった感じで作っていきます。 Add inと比べて、イベントだメッセージだとルールが多くて組みづらい代物ですが、 慣れれば結構楽ですので、それまで頑張りましょう。

3.3 ザウルスのメモリについて

ザウルスのメモリは、内部ワークと本体/カードフラッシュメモリの2種類があります。

内部ワークはパソコンで言うところのメインメモリで、 プログラムの実行や変数その他はここを利用します。 こちらはDRAMですので電源を切れば(電池交換時など)内容が消えます。

本体/カードフラッシュメモリはパソコンで言うところのハードディスクで、 ソフトを入れたり、画像や各種データファイルを入れておく所です。 こちらはフラッシュメモリですので、電源を切っても消えません。 スケジュールやアドレス帳のデータは、当然こちらに記録されます。

通常、メモリ管理で見ることができるのは後者の方で 前者は気づかないのですが、 内部ワークメモリが不足するとmoreソフトを起動できない、 通信できない等の症状が出ます。 これはパソコンで言うところのメインメモリ不足で 満足にソフトが動作できなくなるからです。

なお、この時は裏のスイッチを 『 OFF → 数秒待つ → ON 』とすることで、 リセットがかかり、内部ワークがクリアされて綺麗な状態に戻ります(簡易リセット)。 これは、パソコンで言うところの電源の入れ直しに相当します。

3.4 moreソフトの状態とその遷移

パソコン等の場合、 ソフトはディスクに入っているだけでまだ起動されていない状態と、 実行されて動いている状態の2通りあると思います。 ザウルスの場合、パソコン程はメモリが無いので、 更に実行状態を幾つかに細分化してメモリの有効利用を計っています。
EXIST 状態
単に本体メモリ/カードメモリに入っているだけで実行されていない状態。
OUT 状態
moreソフトが起動され動いている状態ですが、画面は表示していません。
EXEC 状態
moreソフトが起動され画面を表示して動作している状態です。
EXEC状態は以下に示すように、更に ACTIVE状態、非ACTIVE状態 にわけられます。
EXEC-ACTIVE 状態
同時にただ1つのソフトのみがこの状態になります。 ユーザー操作を含む全てのイベントメッセージを受けることができます。
EXEC-非ACTIVE状態
画面再描画や特別のイベント以外は受けつけず、 画面は表示されていてもユーザー操作ができない状態です。 何か別の常駐ソフトがACTIVEになった時に、 それまでACTIVEだったソフトがこの状態に遷移します。
moreソフトは、初めは EXIST状態にあり、実行することで OUT状態へ遷移、 通常はそのまま EXEC状態へと遷移し画面が表示されます (実際にはEXEC状態から各フォーム[画面]が呼び出される)。 この時、時計や電卓などを起動すると、EXEC状態の非ACTIVE状態になり、 ユーザー操作を受け付けなくなります。これは時計や電卓を閉じると 再びACTIVE状態となります。

EXISTOUTEXECフォーム表示
(OUTワーク確保)(EXECワーク確保)(FORMワーク確保)

moreソフトの動作に必要なワークメモリは、 上の表のように各状態に応じて必要なだけのメモリを確保して使うのが基本です。 これにより、OUT状態へ遷移した場合には FORMワーク、 EXECワークを解放して最小のメモリ使用量で済むからです。 画面の遷移にしてもそうです。 例えば画面1から画面2に切り替える時、 同時に両方の画面用のワークエリアは必要ないはずです。 だから一旦フォーム表示の状態からEXECへ戻り、 そこから画面Bを呼び出して画面B用のFORMワークを確保するわけです。

※従って、フォーム間でやり取りしたいデータがあれば、 それはEXECワークに記録しておく方が良いのです。

OUT状態に関しては多少難しいところがありますが、 バックグラウンドで動く必要がなければ終了した方がメモリを無駄にせずに済みます。

ところで常駐型moreソフトを起動した場合、 前のアプリは動いたまま(EXEC)でこちらのソフトが動くのですから、 当然ながらメモリを多量に消費します。 常駐型のソフトではあまりメモリを使わないように工夫した方が良いでしょう。

3.5 各状態遷移時に行うべき事

上にも書きましたが、ザウルスはワークメモリが少ない為、 使わないメモリは極力解放して他が使えるようにしなくてはなりません。

アプリケーション切替時(moreソフト実行中に本体機能を呼んだ時など)には OUT状態にまで遷移するのですが、 状態を遷移させるという事は、すなわち現在の状態を破棄してしまうという事です。 例えば何か編集中だったとして、 そのままOUT状態に移行したのでは編集中の内容が全て無くなってしまいます。

この場合どうするかというと、 現在使用している情報をファイルとして保管してしまうのです。つまり、 OUTに移行する前にEXECワークの中身など保存しておきたい物をファイルに保存し、 再度EXECになった場合に読み込んで設定すれば良いのです。

従ってmoreソフトでは、各状態(OUT,EXEC,各FORM)にきた時点で前の状態を復帰する処理、 各状態から抜ける時に、今の状態を保存する処理が必須となるわけです。 moreソフトを終了しても保存しておきたい情報があれば、 それもファイルとして保管しておく必要があります。

3.6 クラスライブラリ

クラスライブラリというのは、C++などのオブジェクト指向の言語で使われるライブラリなのですが、 SZABではよく使われる”ボタン”や”テキストエディタ”、 ”スクロールバー”などの部品を指してこう呼んでいます。

C言語ですから、基本的にはサブルーチン(関数)呼び出しでしか無いのですが、 これらの汎用部品はメッセージを受け取って動作するという構成になっており、 多少面倒なものの確かにクラスライブラリ的な物です (具体的には、MESSAGE型の構造体に指示やデータを与えてコールするわけです)。

例えば、再描画して欲しいなら・・・
	オブジェクト指向言語的な書き方
		textbox.redisp();

	SZABでの書き方
		localMessage.CommonMsg.MessageID = RedispID;
		ControlCall( textbox, AplForm->Control, &localMessage );
あるオブジェクトのプロパティ width に値 320 を設定したい場合
	オブジェクト指向言語的な書き方
		textbox.width = 320;

	SZABでの書き方
		SetCtrlProperty( textbox, X_WIDTH_PID, usValue, 320, AplForm->Control );
このように、多少(かなり?)面倒な書式にはなりますが、 これで目的は達成できます。後は慣れでしょうか。 実際問題、上のような場合に直接値を入れるよりも、何か共通の関数を作ってしまえば、
	set_width( textbox, 320 );
のような書き方ができるわけですから、そんなに深刻な問題じゃありません。 見えないところで処理されているか、そうでないかといった違いですので。

3.7 アプリケーション識別子

moreソフトを作る場合、アプリケーション識別子と呼ばれる 4byte の固有IDが必要です。 これはmoreソフトのファイル名の頭4文字でもあり、 配布するソフトについては、全て異なるアプリケーション識別子を持っていなくてはならない決まりです。

この識別子の唯一性により、ファイルの重複が避けられるというわけです。

本ドキュメントでは wst3 というアプリケーション識別子を用いていますが、 これは筆者用の識別子ですので、 もしもこれを読んでいるあなたがmoreソフトを作る場合には、 あなた用の識別子を得た上で配布を行ってください。 (詳しくは SZABサポートセンターのページをご覧ください)。

配布は一切行わず、 自分のテストだけであれば tst1 のような識別子で作っても構わないことにはなっていますが、 万が一ぶつかると無用のトラブルを生みますので、くれぐれもご注意ください。

補足事項

ザウルスは、同じアプリケーション識別子を持つソフトは、 本体/カード全てに渡ってただ1つだけでなくてはなりません。 カードと本体メモリの両方に同じ識別子のソフトがあった場合、 moreソフトが動作しない、異常終了するなどのトラブルが起きます。 特に、異なるバージョンの同一ソフトがあった場合など何が起きるかわかりませんので、 気をつけましょう。

3.8 PIM、フォームクラスメソッド関数

moreソフトは起動するまでに、OUT状態、EXEC状態を経てFORM表示へ遷移します。 SZABでは PIMクラス、フォームクラスが大部分の共通処理を行ってくれますので、 各アプリケーション独自の部分があれば、 それ(独自関数)を PIM、フォームクラスメソッドに設定しておき、 各クラスから呼び出してもらうという形を取ります。

つまり、moreソフトを組むという事は、フォーム上での各イベント関数の他に、 これらPIM、フォームクラスメソッドを書きあげるということなんですね。 詳しくは、プログラミングガイドの第7章『PIM、フォームクラスメソッド』にありますが、 ここでは軽くメソッドの呼び出し順と状態遷移をまとめてみました。

表中、括弧で囲んでいるのは PIM、フォームクラスが行ってくれる部分で、 実際に私たちが記述するのは色を付けたところになります なお、フォームメソッドはフォーム=画面ごとに作りますので、 画面枚数だけ異なる名前で作ります。PIMApl****()、 PIMExec****() はアプリケーションに1つです。

・起動(EXIST→FORM表示)の流れ
[EXIST状態]
PIMAplConstruct()OUTワークの確保
全体で必要とするワークメモリを確保(他に考慮して控えめに)
(ZDAM関連ファイル初期化)
PIMAplSetup()OUTワークの内容の初期化やその他準備
[OUT状態]
(IN要求)
(BOXファイルチェック)
PIMExecConstruct()EXECワークの確保
自分が表に出てきたので、たっぷりと必要なメモリを確保
PIMExecSetup()EXECワークの内容の初期化やその他準備
必要なら状態の復元処理
(ZDAM関連ファイルオープン)
(アプリケーションウィンドウオープン)
[EXEC状態]
****FormConstruct()Formワークの確保
(画面上のコントロールが作られる)
****FormSetup()Formワークの初期化、画面コントロールの設定
(エラー発生時、FormError()が呼ばれFormEnd()へ)
(フォーム表示)
[FORM実行中]
****FormEventFilter()イベント配送前に何かする場合これを利用
(リストボックスの列幅制御などはここで)
(画面上のコントロール全てにイベントメッセージ送信)
****FormMenuSelect()メニュー選択時の処理
****FormKeyExec()キー入力(スクロールキー等も)時の処理
****FormOtherEvent()上記で処理されなかったイベントの処理
(一定時間ごとの処理なども)


・停止(FORM表示→EXIST)の流れ
[FORM実行中]
****FormEnd()状態の保存
クラスライブラリの終了処理など(キーボードを消すとか)も必要
Formワークの解放
(画面上のコントロール全て破棄)
[EXEC状態]
(OUT要求)
(アプリケーションウィンドウクローズ)
(ZDAM関連ファイルクローズ)
PIMExecEnd()状態の保存、EXECワークの解放
[OUT状態]
PIMAplEnd()※通常は呼ばれない
(プロセス終了)
[EXIST状態]
※終了時、バックグラウンドでの動作が不要ならば OUT状態を持たずに終了するのが良い。


次のページ 前のページ 目次へ