Q: アップルイベントディスクリプタレコードに保存されているデータはどのようにして取り出せばよいでしょうか?
A: Carbon の Apple Event Manager
API を使って、メモリに直接アクセスし、アップルイベントディスクリプタレコードに関連付けられているデータを取り出すことはできません。アップルでは、AEDesc 構造体に保存されているデータのコピーを取得するための、2 つの Carbon アクセッサ API (AEGetDescDataSize と
AEGetDescData)を提供しています。これら 2 つの API の適切な使用方法については、リスト 1 に示します。
AEDesc レコードに保存されているデータを変更するために、アプリケーションにおいて
AEReplaceDescData ルーチンを使うことができます。
背景知識
AEDesc 構造体には、ディスクリプタ型フィールドとデータフィールドの 2 つのコンポーネントが含まれています。ディスクリプタ型フィールドには、ディスクリプタレコードに保存されているデータの型を識別する 32 ビットのコード(4 文字の ASCII 文字の場合が多い)が含まれています。データフィールドは、ディスクリプタレコードと関連付けられているデータへの参照を保存するために、Apple Event Manager
によりシステム内部で使用されます。
リスト 2 は AEDesc
構造体の宣言を示します。
|
リスト 2 AEDesc 構造体の宣言
|
typedef AEDataStorageType *AEDataStorage;
struct AEDesc {
DescType descriptorType; /* データ型フィールド */
AEDataStorage dataHandle; /* データフィールド */
};
|
Mac OS X より前のバージョンの Mac OS における Apple Event Manager の実装では、AEDesc に関連付けられている情報を Carbon Memory Manager Handleが参照するメモリブロックに保存するために dataHandle フィールドを使っていました。しかし、Carbon
API と Mac OS X の登場で、AEDesc の dataHandle フィールドは、不透過のポインタ型に変更されました。この変更に伴い、ソフトウェアがこのフィールドの中身について何らかの仮定をするのは不適切となりました。
|
警告:
AEDesc 構造体の dataHandle フィールドに保存されている値を使っている、あるいは dataHandle フィールドに Carbon
Memory Manager Handle が含まれていることを仮定するコードは、現在サポートされておらず、また Mac OS X における Apple Event Manager の今後の実装では機能しないかもしれません。
|
AEDesc 構造体自体は不透過ではありません。したがって、アプリケーションソフトウェアが、AEDesc レコードに保存されているデータ型を確かめるために descriptorType フィールドにアクセスすることは可能です。
しかし、アプリケーションでは、dataHandle フィールドに保存されている値の意味について何らかの仮定をするべきではありません。最高の結果を得るには、リスト 3 に示すように、dataHandle フィールドの内容に依存しない、内容について仮定しないコードを構築すべきです。
|
リスト 3 AEDesc レコードの dataHandle フィールドに保存されている値を使わないコードの構築例
|
AEDesc theDesc;
char* p = "Hello World";
/* ディスクリプタを作成する */
err = AECreateDesc(typeChar, p, strlen(p), &theDesc);
if (err == noErr) {
/* 作成したディスクリプタを使って何らかの操作を実行する */
/* ディスクリプタを削除する */
AEDisposeDesc(&theDesc);
}
|
ルールの例外
AEDesc レコードに関連付けられているデータがあるかどうかを確かめるために、リスト 4 に示すように、コードにおいて、dataHandle フィールドを NULL と比較するのは構いません。しかし、その他の形で dataHandle フィー
ルドを使っても意味はありません。
|
リスト 4 AEDesc レコードの dataHandle フィールドについて安全な仮定をしたコードの例
|
AEDesc d = { typeNull, NULL }; // 新しい空のディスクリプタを初期化する
if (d.dataHandle != NULL) // ディスクリプタが空でないかどうかを調べる負担の軽いチェック
|
[2002 年 4 月 10 日]
|