MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSA Developer News[MOSADeN=モサ伝]第148号

2005-02-15

目次

  • SqueakではじめるSmalltalk入門  第30回  鷲見 正人
  • 小池邦人の「Carbon API 徒然草」
  • 「Behind the WebObjects」    第37回  田畑 英和
  • ニュース・解説   木下 誠

SqueakではじめるSmalltalk入門   第30回  鷲見 正人

 本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。

 ブロックは、手続きをオブジェクトとして扱うためのものとして存在し、処理結果ではなく手続きごと受け渡しを可能とすること。また、Smalltalkではその特性を利用し、ブロックをメソッド(関数)のパラメータ(引数)に添えることで様々な制御構造を実現していること、について書きました。今回はブロックの扱いの最後として、Smalltakにおける並列処理について簡単に触れます。

 まず、次のようなスクリプトを考えてみましょう。行頭にはコメントのかたちで行番号を振ってあります。

"01"   | array size |
"02"   size _ 10.
"03"   array _ Array new: size.
"04"   1 to: size do: [: idx |
"05"      array at: idx put: #a].
"06"   ^ array

 このスクリプトは、sizeに束縛したサイズの配列を作り、その要素を#aで埋めます。print it (cmd-P) で評価し、結果を得ることが可能です。

#(#a #a #a #a #a #a #a #a #a #a)

 三行目から四行目、1に対して送信されるto: size do: [...]というメッセージ式は、前回紹介したように、1からsizeまでを繰り返す、いわゆるfor-nextループ処理をシミュレートしています。#at:put:は、配列の指定した要素に指定したオブジェクトを束縛するためのメソッドです。

 この式の前後を[ ]で括るとブロックにできることと、ブロックは、value(ブロック変数のあるときは、value: arg、value: arg1 value: arg2、…)というメッセージを受けることで、自身に記述された手続きを評価して結果を返すことはすでに何度かご説明したとおりです。そこで、次のように書いても上のスクリプトと同じことになります。

| array size |
size _ 10.
array _ Array new: size.
[1 to: size do: [: idx |            "<= 行頭に[を追加"
   array at: idx put: #a]] value.   "<= 行末に] valueを追加"
^ array   " => #(#a #a #a #a #a #a #a #a #a #a) "

 このvalueの代わりに「fork」を送信することで、ブロックに記述した手続きを別のスレッドにフォークする、つまりプロセスを“枝分かれ”させることが可能です。拍子抜けするほど簡単ですね。

| array size |
size _ 10.
array _ Array new: size.
[1 to: size do: [: idx |
   array at: idx put: #a]] fork.   "<= valueをforkに変更"
^ array   " =>  #(nil nil nil nil nil nil nil nil nil nil) "

 要素を#aで埋める作業は、別スレッドで行なわれるので、print it (cmd-P)の結果では、まだ、配列は作られた直後の状態、つまりすべての要素はnil(未定義値)のままです。余談ですが、print itの代わりにinpect it (cmd+I)すると、不思議なことに今度は中身が埋まった状態になります。これは、インスペクタを起動している間にフォークした処理が終わるからです。

 これはこれでおもしろいのですが、何かと不便なので、フォークした処理が終わるまで待ってから結果を表示させるようにしましょう。

| array size |
size _ 10.
array _ Array new: size.
[1 to: size do: [: idx |
   array at: idx put: #a]] forkAndWait.  "<= forkをforkAndWaitに"
^ array   " =>  #(#a #a #a #a #a #a #a #a #a #a) "

 #forkAndWaitは、フォークする処理が終わるまで待つセマフォ(a Semaphore。腕木信号機)を内部的に介在させ、自動的に同期をとってくれるメソッドです。興味があるかたは、forAndWaitを選択しbrowse it (cmd + B)で定義を見てください。

 では、このスクリプトに、今度は#aではなく、#Aで要素を埋める手続きを追加してみましょう。もちろんブロックとして記述し、プロセスはフォークさせます。

| array size |
size _ 10.
array _ Array new: size.
[1 to: size do: [: idx |           "<= 追加"
   array at: idx put: #A]] fork.   "<= 追加"
[1 to: size do: [: idx |
   array at: idx put: #a]] forkAndWait.
^ array   " =>  #(#a #a #a #a #a #a #a #a #a #a) "

 しかし結果は追加以前と変わりません。Squeakシステムの並列処理は優先順位が同じなら、フォークされた順に待ち合わせ、逐次実行されるからです。順番待ちしている別のスレッドに実行のチャンスを与えるには、Processor yieldというメッセージ式を処理の途中に挿入しておく必要があります。

| array size |
size _ 10.
array _ Array new: size.
[1 to: size do: [: idx |
   array at: idx put: #A.
    Processor yield]] fork.
[1 to: size do: [: idx |
   array at: idx put: #a.
   Processor yield]] forkAndWait.
^ array   " => #(#a #A #a #A #a #A #a #A #a #A) "

 Processはa ProcessSchedulerを束縛するグローバル変数で、プロセスの監視役です。yieldを受信すると、実行中のプロセスをいったん中断し、待ちプロセスに機会を与えます。これで仲良くスレッド間で譲り合って要素を埋めてゆくので、結果は#A、#aの交互になります。

 valueとほぼ同じ感覚で利用できるforkですが、評価結果を返すvalueと違い、forkはフォークした処理本体(a Process)を返します。これをグローバル変数などに束縛しておけば、任意のタイミングで、suspendやresumeを送信して一時停止や再開、あるいは、terminateを送信することで失効させることが可能です。次のスクリプトは画面左上に現在時刻を表示します。

Smalltalk at: #TIMER put: nil.   "グローバル変数TIMERの定義"
TIMER _ [
    [Time now print24 displayAt: 10 @ 10.
    (Delay forSeconds: 0.1) wait] repeat] fork

 ここでフォークされるプロセスは、repeatを使った永久ループになっているので、先の例のように自動的には停止しません。止めるには、次のメッセージ式を評価します。

TIMER terminate

バックナンバー:
http://squab.no-ip.com:8080/mosaren/

小池邦人の「Carbon API 徒然草」(2005/02/11)

Navigation Service APIの活用(その4)

今回は、「フォルダ選択」や「ファイル読み込み」に用いられるNavigation Service APIを説明します。具体的には、ダイアログのブラウザからファイルやフォルダを選択することができる、NavChooseFolder()とNavGetFile()についての解説となります。

まず最初に、ユーザが選択したフォルダのFSSpecを得るためのnavMyChooseFolder()ルーチンを紹介します。ダイアログを表示するまでの手順は、navMyPutFile()の時とほぼ同じですが、異なるのは、opt.preferenceKeyに別の識別値’IMGE’を代入している点と、複数ファイルの選択を禁止するために、opt.dialogOptionFlagsのkNavAllowMultipleFilesビットをクリアしている点です。代入する識別値をnavMyPutFile()の時と変えているのは、作業の対象となるファイルの種類が異なるためです。前回はドキュメントファイルが対象でしたが、今回は画像ファイルが対象であり、作業内容に準じたディフォルト表示位置をシステム側に憶えておいてもらうために、異なる識別値を設定しているわけです。

short navMyChooseFolder( FSSpec *fsc )
{
    NavReplyRecord      reply;
    short               ret=1;
    DescType            rtype;
    NavDialogOptions    opt;
    Size                len;
    AEKeyword           key;

    NavGetDefaultDialogOptions( &opt );     // ダイアログのオプションを初期化
    opt.preferenceKey='IMGE';               // 使用形態を識別するための値を設定
    opt.dialogOptionFlags+=kNavNoTypePopup; // 種類ポップアップメニューを外す
    opt.dialogOptionFlags-=kNavAllowMultipleFiles; // 複数フォルダの選択を禁止
    GetIndString( opt.clientName,128,1 );   // クライアント名をリソースから得る
    if( ! NavChooseFolder( NULL,&reply,&opt,NULL,NULL,NULL ) ) //ダイアログ表示
    {
        if( reply.validRecord )     // OKボタンが押された場合...
            ret=AEGetNthPtr( &(reply.selection),1,typeFSS,&key,&rtype,(Ptr)fsc,
                                                        sizeof(FSSpec),&len );
                                    // 選択フォルダのFSSpecを得る
        NavDisposeReply( &reply );  // NavReplyRecordを削除する
    }
    return( ret ); // ret==noErrであればOKボタンが押されたことになる
}


続いて「ファイル読み込み」に用いられるnavMyGetFile()ルーチンです。こちらは、「ドキュメント読み込み」と「画像ファイルの登録」という2つの用途に使われるため、最初の引数(kind)の内容により、ダイアログ表示までの準備手順を分岐しています。具体的には、kindがゼロならばドキュメントオープン用として、kindが1であれば画像ファイル登録用として働きます。また、このルーチンからは複数のFSSpecやファイルタイプが返されますので、それらを格納するための配列と、その個数の格納場所である*ctも同時に引数として渡します。この時の配列の最大数(読み込みファイル最大数)については、ヘッダーファイルにMAX_BUF(200個まで)として定義されています。

#define   MY_SIG   'MosA'   // アプリケーションのシグネイチャ
#define   MY_DOC   'MosD'   // ドキュメントのファイルタイプ
#define   MAX_BUF  200      // 一度で読み込む最大のファイル数

short navMyGetFile( short kind,OSType type[],FSSpec fsc[],unsigned long *ct )
{
    OSType              type1[200];
    long                i,max;
    NavReplyRecord      reply;
    DescType            rtype;
    short               ret=1;
    short               nb=1;
    unsigned long       nn=0;
    NavTypeListHandle   list;
    FSSpec              fsc1;
    NavDialogOptions    opt;
    Size                len;
    AEKeyword           key;
    FInfo               ff;

    *ct=0;
    len=sizeof(FSSpec);

    NavGetDefaultDialogOptions( &opt );     // ダイアログのオプションを初期化
    GetIndString( opt.clientName,128,1 );   // クライアント名をリソースから得る
    opt.dialogOptionFlags+=kNavNoTypePopup; // 種類ポップアップメニューを外す

    if( kind==0 )           // ドキュメントファイルをオープンするための設定
    {
        opt.preferenceKey=MY_SIG;         // 使用形態を識別するための値を設定
        type1[0]=MY_DOC;
    }
    else                    // 画像ファイルをオープン(登録)するための設定
    {
        opt.preferenceKey='IMGE';          // 使用形態を識別するための値を設定
        navGetImportTypeList( type1,&nb ); // QuickTime読み込み可能タイプ
        type1[nb++]=NULL;                  // タイプが設定されていない場合
        type1[nb++]='????';
        type1[nb++]='****';
        type1[nb++]='    ';
    }
    navMakeTypeList( nb,type1,&list ); // 表示対称となるType Listを作成する

    if( ! NavGetFile( NULL,&reply,&opt,NULL,NULL,NULL,list,NULL ) ) // 表示する
    {
        if( reply.validRecord )    // OKボタンが押された場合...
        {
            AECountItems( &(reply.selection),&max ); // 選択ファイル数を得る
            if( max > MAX_BUF )                      // 最大数で制限をかける
                max=MAX_BUF;
            for( i=1;i<=max;i++ )
            {
                if( ! AEGetNthPtr( &reply.selection,i,typeFSS,&key,&rtype,
                                           (Ptr)&fsc1,sizeof(FSSpec),&len ) )
                                              // 選択ファイルのFSSpecを得る
                {
                    FSpGetFInfo( &fsc1,&ff ); // ファイル情報を得る
                    navCheckImportExtention( fsc1.name,&ff.fdType );
                                              // ファイルの拡張子を調べる
                    type[nn]=ff.fdType;       // 得られたファイルタイプを格納
                    fsc[nn++]=fsc1;           // 得られたFSSpecを格納
                    ret=0;
                }
                else
                    break;
            }
            NavDisposeReply( &reply );        // NavReplyRecordを削除する
        }
    }
    DisposeHandle( (Handle)list );            // 作成したNavTypeListHandleを削除
    *ct=nn;                                   // 選択ファイル個数を返す
    return( ret );
}


用途により分岐させている箇所の目的は、ブラウザに表示させるファイル種類を切り替えることです。その準備として、表示対象とするファイルタイプを配列list1(OSType)へと順次代入していきます。ドキュメントの場合にはMY_DOCをひとつだけセットしていますが、画像ファイルの場合は、まず第一にQuickTime Importerが読み込み可能な画像ファイルタイプ(JPEG,PICT,TIFFなど)をnavGetImportTypeList()ルーチンを使い代入します。しかし、これだけですと、ファイルタイプが設定されていない(NULLの)画像ファイルはブラウザへは表示されません。やっかいなことに、Mac OS X環境では、ファイルタイプが設定されていないため、その種類をファイル名の拡張子から判断しなければならない画像ファイルが沢山存在します。それらをちゃんと表示するためには、NULLを含めたいくつかの特殊なファイルタイプも配列へ追加しておく必要があります。こうして配列へ代入したファイルタイプは、navMakeTypeList()ルーチンによりNavTypeListHandleへと作り直されて、NavGetFile()に渡されます。

画像ファイルのFSSpecを得る処理が、navMyChooseFolder()の場合と大きく異なるのは、ユーザにブラウザ上での複数ファイルの選択を許しているためです(最大数の制限はある)。まずは、AECountItems()によりファイル選択数を調べ、その個数分のファイルタイプとFSSpecを順次配列に格納します。ファイルタイプの方は、先んじてFSpGetFInfo()で得ておき、その値がNULLであるかどうかをnavCheckImportExtention()ルーチンに渡して調べるようにします。もしそれがNULLであれば、navCheckImportExtention()がファイル名の拡張子を調べることで正しく作り直します。例えば拡張子が.jpgであれば、ファイルタイプは'JPEG'と設定し直されるわけです。

次回は、navMyGetFile()で呼ばれているnavGetImportTypeList()、navMakeTypeList()、navCheckImportExtention()の3つの自作ルーチンを解説することで、ファイル選択時の悩みの種である「ファイルタイプ」と「拡張子」の共存問題について考えてみます。

「Behind the WebObjects」  第37回  田畑 英和

 いよいよMac OSに対応したOracleの発売が開始されます。ニュースリリースによれば2/25より「Oracle Database 10g for Apple MAC OS X」の出荷開始が開始され、対応OSは「Mac OS X Server」となっています。これでまたMac上で利用できるデータベースが増えたことになります。またデータベースだけではなく開発環境の「Oracle JDeveloper 10g for MAC OS X」も同じく2/25から提供開始となります。
 2/24, 2/25に東京国際フォーラムで開催される「Oracle 10g World」では、Mac版のOracleに関するセッションも予定されており、オラクル技術者向けのサイトでは試用版の提供が開始されています。

・Oracle社ニュースリリース
http://www.oracle.co.jp/news_owa/NEWS/news.news_detail?p_news_code=1301
・Oracle Technology Network Japan
http://otn.oracle.co.jp/

 WebObjectsといえばデータベースと連携したシステムを構築することがなにかと多く、どのようなデータベースを選択するのがよいか考えていかなければなりません。そこで今回はWebObjectsから利用可能なデータベースについて紹介いたします。

WebObjectsが公式に対応しているデータベース

・Microsoft SQL Server 2000
・MySQL 3.23.51
・OpenBase 7.0.8
・Oracle 8.1.7 and 9.2.0.1
・Sybase ASE 12.5

 これらが正式にサポートされているデータベースになります。ご覧になっていただいてお分かりのように、けして各データベースの最新版をサポートしているわけではなく、中には今となっては最新版のMac OS Xに完全に対応していないものもあります。
 MySQLは4.1系列のバージョンがリリースされており、WebObjectsのパッケージにもバンドルされているOpenBaseは現在8.0.4(b20)がリリースされています。今回新しくリリースされるOracleは最新版の10gになり、Sybaseについては正式にサポートされているASE 12.5が現在でも最新のバージョンとなっています。必ずしも最新バージョンを使えばよいというわけでもないですが、古いバージョンを使用することのデメリット(例えばサポートの対象外になるなど)を考えれば、積極的な最新環境への対応が望まれます。
 また公式サポートには含まれていませんが、PostgreSQLやFrontBaseといったデータベースも利用することができます。

・WebObjects Compatibility Guide
http://docs.info.apple.com/article.html?artnum=72598
・FrontBase
http://www.frontbase.com

OpenBase

 それでは、これらのデータベースからOpenBaseとMySQLの概要を簡単に解説したいと思います。まずはOpenBaseですが、こちらはNeXT時代から開発が続けられているデータベースであり、WebObjectsにバンドルされていることもあってWOの開発者であればなにかとおなじみのデータベースです。
 簡単にデータベースの管理がおこなえるツール「OpenBase Manager」が付属していて、さほど高度なスキルがなくともデータベースの管理をおこなうことができます。トランザクション制限があるPsersonal版は無料で使用することができ、トランザクション無制限であっても$1,999からと比較的低価格なデータベースです。昨年はマウイ島でOpenBase Developers Conferenceが開催され、日本から参加された方もいらっしゃったようです。
 前回紹介しましたWebObjectsに付属するサンプルがOpenBaseを使用していたりもしますので、これからWebObjectsを始めるかたはまずはOpenBaseを利用してはいかがでしょうか。

・OpenBase
http://www.openbase.com

MySQL

 オープンソースのデータベースであり高速性を特長としています。Mac OS X Serverにも搭載されていまして、専用の管理ツールも付属するのですが、初期化と起動/停止程度の機能しかなく、通常は「Terminal」を用いてコマンドライン上での操作が必要になります。
 GUIでの管理をおこなう場合は「CocoaMySQL」を利用することができます。このツールを用いればGUI上でMySQLの管理ができます。データベースやテーブルの編集機能があり、データベースに格納されているデータをブラウズすることもできます。
 もともとMySQLはMac OS X用にビルドされたバイナリーも標準で提供されていますが、MySQL用のシステム環境設定やJDBCドライバをセットにしたパッケージ「Complete MySQL」を利用することもできます。

・MySQL
http://www.mysql.com/
・CocoaMySQL
http://cocoamysql.sourceforge.net/
・Complete MySQL
http://www.serverlogistics.com/mysql.php

JDBC接続

 WebObjects 5.0以降はリレーショナルデータベースへの接続としてJDBCを用いていますが、JDBCではURLを指定することによりデータベースへの接続情報を設定します。
 基本的なURLの形式は同じなのですが、データベースごとに適切なパラメータを用いる必要があり、特に特定のエンコーディングを指定するときには注意が必要です。TILでJDBCのURLに関する情報が公開されていますので、こちらを参考にしてください。

・WebObjects 5.xから各種データベースへの接続
http://til.info.apple.co.jp/techinfo/100473
・JDBC URL を指定してデータベースサーバの文字エンコードを選択する方法
http://til.info.apple.co.jp/techinfo/107856

 さて、今回はデータベースについて簡単に解説いたしましたが、いかがでしたでしょうか。TigerになるとすべてのMac OS XにSQLiteというデータベースが付属するようにもなりますし、Cocoaベースのオプジェクト永続化フレームワークCoreDataも利用できるようになり、そのリリースが待ち遠しいです。それではまた次回。

ニュース・解説

今週の解説担当:木下 誠

----------------------------------------------------------------------
Oracle Database 10gとOracle JDeveloper10gが出荷予定
----------------------------------------------------------------------
日本オラクルが、最新データベース「Oracle Database 10g」とJavaアプリケーションIDE「Oracle JDeveloper 10g」を、Mac OS X Serverに対応させ、2月25日より出荷すると発表していました。これにより、オラクルのデータベースをMac OS X Serverで利用でき、サポートも受けられることになります。
「Oracle Technology Network Japan (http://otn.oracle.co.jp/)」より、試用版がダウンロードできます。

Appleは「Oracle Database 10g on Mac OS X Server」というページを公開し、X Serverとオラクルの紹介を行っています。また「Using Oracle JDeveloper on Mac OS X」というページで、JDeveloperのチュートリアルを公開しています。

2月24日〜25日に東京国際フォーラムで開催される、Oracle 10g World(セッションB-6)にて「いよいよ登場!Oracle Database 10g on Mac OS X全貌」と題したセミナーを行い、製品の紹介を行うそうです。

Oracle Technology Network Japan
http://otn.oracle.co.jp/

Oracle Database 10g on Mac OS X Server
http://www.apple.com/server/resources/oracle/

Using Oracle JDeveloper on Mac OS X
http://developer.apple.com/tools/jdeveloper.html

OracleとApple、ともに新規市場へ - Oracle 10g、OS X Serverをサポート
http://pcweb.mycom.co.jp/news/2005/01/31/008.html

Oracle 10g World
http://www.oracle.co.jp/events/10g_2005/top.html

----------------------------------------------------------------------
Xcode 2.0の紹介
----------------------------------------------------------------------
Appleが、Tiger Developer Overview Seriesの最新作、「Working with Xcode 2.0」を公開していました。Tigerで導入される、新しいバージョンのXcodeを紹介しています。

Xcode 2.0の目玉は、コードの可視化機能になるようです。UMLライクな図で、コード全体を眺めることができます。可視化モデルには、クラスモデルとデータモデルの2つがあります。クラスモデルは、クラス階層およびクラス情報を表示するモデルで、Objective-C、C++、Javaに対応しています。編集中のソースコードとの、ダイナミックな同期もサポートされます。データモデルは、Core Dataと連携するモデルで、モデルのオブジェクトグラフを作成、管理します。おそらく、WebObjectsを使っている方には、馴染みやすいでしょう。

その他には、Search Kitやネットワーク上のリソース同期にも対応した新しいドキュメントブラウザ、レイアウトの自由度が高くなったワークスペース、最新版であるGCC 4.0、などが含まれます。

Working with Xcode 2.0
http://developer.apple.com/macosx/tiger/Xcode2.html

----------------------------------------------------------------------
テクニカルQA: Audio Unitのバージョンを調べる
----------------------------------------------------------------------
「Technical Q&A QA1408: Determine the version of an Audio Unit」が公開されていました。現在のシステムで使用可能なAudio Unitのバージョンを調べる方法が解説されています。GetComponentVersion を使うようです。

最近は、Core Audioの活動が活発ですね。

QA1408: Determine the version of an Audio Unit
http://developer.apple.com/qa/qa2005/qa1408.html

----------------------------------------------------------------------
Property List Editorの機能強化版シェアウェア
----------------------------------------------------------------------
Brian Webster's Home Pageより、PlistEdit Proが配布されています。これは、Property Listを編集するためのエディタで、Appleが配布しているProperty List Editorの機能強化版になっています。

主な機能は、ドラッグ・アンド・ドロップとコピー・ペーストのサポート、アンドゥサポート、フルキーボードナビゲーション、アウトラインとテキストでの編集、Apple Script対応、などとなっています。$24.95 のシェアウェアです。

AppleのProperty List Editorは機能が貧弱なので、有用だと思います。また、Property Listのエディタは、必要な機能が標準でそろっているので、プログラミングの練習の課題としてもいいのではないでしょうか。

PlistEdit Pro
http://homepage.mac.com/bwebster/plisteditpro.html

MOSAからのお知らせと編集後記は割愛します

MOSA Developer News   略称[MOSADeN=モサ伝]
Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
このメールの再配信、および掲載された記事の無断転載を禁じます。
特定非営利活動法人MOSA  http://www.mosa.gr.jp/
Copyright (C)2005 MOSA. All rights reserved.