Chapter 4:
初期化ルーチン

作成される共有ライブラリは、main 関数の開始アドレスを持っています。このアドレスは、ロードの際に外部から認識される唯一のエントリポイントです。 main関数はただ1回だけ、コードリソースがロードされる際に呼び出され、オブジェクトのクラスを初期化します。これは、次のように書かなければなりません。

void *myobject_class; /*クラスへのポインタ */ void *myobject_create(void); void myobject_free(myObject *x); void main(void *p) { setup(&myobject_class, myobject_create, myobject_free, (short)sizeof(myObject), 0L, 0); /* クラスメモリのアロケートとクラスのセットアップ */ /* ここに、addmess, addint, addbang,等を使用した add メッセージ*/ /* ここに、rescopyを使用したリソースのコピー */ }

クラス定義のルーチン

このセクションでは、初期化(main)ルーチンで使用するいくつかの関数について述べます。

setup

setup 関数を使ってクラスを初期化します。これによりMaxにクラスのサイズ、インスタンスを生成・消滅させる関数名、インスタンス生成関数に渡される引数の型を知らせます。

void setup (t_messlist **class, method createfun,method freefun, short classSize, method menufun, short types...);
   
class コードリソースの中のグローバル変数、初期化されるクラスへのポインタ
createfun インスタンス生成関数
freefun インスタンス消滅関数(Chapter 7を参照)
classSize オブジェクトのデータ構造体のサイズ(バイト)、通常ここではCの sizeof 演算子を使用
menufun ユーザインタフェイスオブジェクトを定義するときにのみ使用。 この関数は、ユーザがパッチャーウィンドウのパレットから新しいこのクラスのオブジェクトを作った時に呼び出されます。ユーザインタフェイスオブジェクトを定義していない場合には0が渡されます(この関数の書き方はChapter 11 で説明します) 。
types Chapter 3 で説明した標準的なMaxの型リスト。型リストの最後の引数は0でなければなりません。このリストはクラスの新しいインスタンスが作られる際に必要な引数を指定します。これらは、ユーザがクラス名の後に続けるアーギュメントになります。

実例として、1つの整数をアーギュメントに取る、+ と呼ばれるオブジェクトのクラスを定義する場合を考えて下さい。値20がオブジェクトのインスタンス生成関数に渡されます。

このクラスの構造体定義です。

typedef struct myobj { struct object m_ob; long m_watchtower; } Myobj;

生成、消滅関数のプロトタイプ宣言です。

void *myobj_new (long arg); void myobj_free (MyObj *x);

クラスへのポインタとなるグローバル変数です。

void *myobj_class;

setup を呼び出す初期化ルーチンの初めの部分です。

void main(void *p) { setup (&myobj_class, myobj_new, myobj_free,(short)sizeof(Myobj), 0L,A_DEFLONG,0); /* ここに追加のコードを書きます */}

setup の呼び出しが終了すると明確な形を持ったクラスが存在するようになりますが、これがどのような動作をするかはまだわかりません。これを役立つものにするためには、メッセージに対応したクラスを作る必要があります。 このことは、t_symbol(bangのような語)を、開発者によって書かれた関数(しばしば、メソッドと呼ばれます)に関連づける(バインドする)ことを意味しています。これを行なうために使用する関数については、すぐ後で述べたいと思います。Maxにはクラスに標準的なメッセージを簡単に追加できるように設計された関数が用意されていて、addmess はその1つです。これらにより、新しいメッセージを指定して、Maxによって型チェックが行なわれるアーギュメントを与えることができます。

rescopy

初期化ルーチンが終わった後、エクスターナルオブジェクトのコードリソースファイルから、使いたいリソースをコピーするためには、rescopy を使います。

void rescopy (OSType resType, short resID)
   
resType コピーしたいリソースの4文字のリソースタイプ
resID コピーしたいリソースのID

コードリソースやその他のリソースを含むファイルは、初期化処理の後に閉じられます。したがって、ダイアログやメニュー等何らかのMacintoshのリソースをオブジェクトの中で使用したい場合には、これらをコードリソースファイルからコピーする必要があります。rescopy は指定したリソースをオリジナルのファイルから"Max Temp"と呼ばれるテンポラリのリソースファイルにコピーする関数です。このファイルはTemporary Ites フォルダに置かれます。Maxが実行されている間にコンピュータがクラッシュした場合、このファイルは「ゴミ箱」に入れられます。

rescopy は初期化の際にだけ使用されると考えられています。これはMaxがロックされたメディアで実行されている場合にも働きます。リソースがコピーされると、それに対していつでもアクセスすることができます。rescopy は正常に実行されれば0を返します。そうでない場合、Maxウィンドウにエラーメッセージが表示され、rescopy は-1を返します。リソース名は、1つしかない場合にはリソースがコピーされる際に保存されます。

Windows XP 上でエクスターナルをコンパイルする場合、この動作を行うためにはリソースタイプで FOUR_CHAR_MACRO を使う必要があります。(このマクロは Macintosh 上では何もしないよう定義されています)

rescopy(FOUR_CHAR_CODE(‘str#’),7474);

Macintoshのリソースファイルは、MacOS 9 の遺物です。したがって、時と場所を問わず、可能な限りこれを使用しないことを推奨します。

resnamecopy

初期化ルーティンが終了した後で、エクスターナルオブジェクトのコードリソースファイルからリソース名を使ってリソースをコピーするためには、resnamecopy を使います。

void resnamecopy (OSType resType, char *name)
   
resType コピーしようとするリソースのリソースタイプを表す4文字
name コピーしようとするリソースの名前のCストリング.

rescopy と同様、可能な限り Macintosh リソースファイルを使用しないようアドバイスします。

予約済みリソース

リソースは、Max自身のリソースや他のエクスターナルオブジェクトのナンバとかち合わないようにナンバを設定しなければなりません。Maxの持っているリソースIDは、Maxアプリケーションを ResEdit で覗いて見ることでわかります。これは、Maxで使われる一般的なリソースタイプの予約範囲です。

ALRT 1000-1099, 1300-1399
CNTL 1000-1099
DITL 257, 1000-1099, 1300-1399
MENU 128-255
DLOG 257, 1000-1099, 1300-1399
STR# 1000-1199, 3000-3799, 4000-4099, 5000-5099, 7000-7099
PICT 344, 501-509, 888, 4200-4299, 8800-8899, 14914

さらに、Maxに含まれるエクスターナルのID範囲は、STR#、DITL、DLOGの3000〜3700になっています。この範囲は避けておくことが賢明です。

alias

alias 関数はユーザがオブジェクトを、共有ライブラリ名と異なる「名前」で参照することを可能にします。

void alias (char *name)
   
name あなたのクラスのオブジェクトをユーザが使用する時のための名前(エイリアス)

この関数は、ユーザがあなたのオブジェクトを共有ライブラリ名ではなく、「名前」で参照することを可能にします。これは、「楕円、または長方形を作ることができる描画オブジェクト」等のように、作成するエクスターナルオブジェクトが多くの可能な処理を持っている場合、便利かもしれません。型リストのA_GIMMEsetup 関数を呼び出した場合(これについては後で説明します)、あなたのオブジェクト生成関数はユーザがオブジェクトを作る時に入力した名前を見つけることができます。

しかし、事は単純ではありません。ユーザがオブジェクトの名前を入力して動的にロードする場合、ファイル名はオブジェクト名と同じでなくてはなりません。したがって、alias を使用する場合、オブジェクトを起動時にロードする(または、Fileメニューのinstall...を使用する)必要があることをユーザに知らせる必要があります。さもないと、エイリアス名を参照したときに"no such object"というエラーが返ってきてしまうことになります。

この問題は、MacOSのエイリアス機能を利用することによって多少改善できます。Maxはファイルのエイリアス名をオブジェクト名として解決することができるためです。Maxの alias 関数で用意した名前と同じ名前を持つ、ファイルのエイリアスを作り、これを利用することができます。エクスターナルオブジェクト "henry" が "hank"というエイリアス名を持っている場合、"henry" というMaxのエクスターナルファイルを選択し、FinderのFileメニューの「エイリアスを作る」を選んで、そのエイリアスの名前を "henry" から"hank"に変更します。

class_setname

class_setname を使うと、オブジェクト名とそのディスク上のファイル名を結びつけることができます。

void class_setname (char *obname, char *filename);
   
obname Max 上で表される、オブジェクトのクラス名の文字列
filename ディスク上で表される、エクスターナルの名前の文字列

オブジェクトが、オブジェクトボックスでタイプされる名前とは異なるファイル名を持つ可能性もあります。この場合、 class_setname を用いて、オブジェクト名とファイル名を結びつける必要が生じます。例としては、オブジェクト名に英数以外の文字が使われている場合、OSによってはファイル名としては規約違反になってしまう場合が挙げられます。 (オブジェクト名が "/"で、ファイル名が "div"のような場合)