高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Q&A QA1139
Retrieving Data from AEDesc Records - do not use the dataHandle field


Q: アップルイベントディスクリプタレコードに保存されているデータはどのようにして取り出せばよいでしょうか?

A: Carbon の Apple Event Manager API を使って、メモリに直接アクセスし、アップルイベントディスクリプタレコードに関連付けられているデータを取り出すことはできません。アップルでは、AEDesc 構造体に保存されているデータのコピーを取得するための、2 つの Carbon アクセッサ API (AEGetDescDataSizeAEGetDescData)を提供しています。これら 2 つの API の適切な使用方法については、リスト 1 に示します。



リスト 1. AEGetDescDataSizeAEGetDescData を使用して AEDesc レコードに保存されているデータのコピーを取得

Ptr theData;
Size theLength;
AEDesc theDesc;
OSStatus err;

    ....

    /* ディスクリプタレコードに保存されている
    データの長さを調べる */
theLength = AEGetDescDataSize(&theDesc);

    /* データのコピーを保持するためのバッファを割り当てる*/
theData = malloc(theLength);
if (theData != NULL) {

        /* データをバッファにコピーする */
    err = AEGetDescData(theDesc, theData, theLength);
    if ( err == noErr) {

        /* 取得したデータで何らかの操作を実行する*/

        ....


AEDesc レコードに保存されているデータを変更するために、アプリケーションにおいて AEReplaceDescData ルーチンを使うことができます。



重要:
AEGetDescData ルーチン、AEGetDescDataSize ルーチンおよび、 AEReplaceDescData ルーチンは、単純な値を保存するディスクリプタにのみ使用できます。AppleEvent レコード、AERecord レコード、 および AEDescList レコードのような複合型のディスクリプタレコードには使えません。複合型のディスクリプタレコードにこれらのルーチンを使おうとすれば、予期しない結果が生じ、アプリケーションがクラッシュする場合があります。



背景知識

AEDesc 構造体には、ディスクリプタ型フィールドとデータフィールドの 2 つのコンポーネントが含まれています。ディスクリプタ型フィールドには、ディスクリプタレコードに保存されているデータの型を識別する 32 ビットのコード(4 文字の ASCII 文字の場合が多い)が含まれています。データフィールドは、ディスクリプタレコードと関連付けられているデータへの参照を保存するために、Apple Event Manager によりシステム内部で使用されます。 リスト 2AEDesc 構造体の宣言を示します。



リスト 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 の登場で、AEDescdataHandle フィールドは、不透過のポインタ型に変更されました。この変更に伴い、ソフトウェアがこのフィールドの中身について何らかの仮定をするのは不適切となりました。



警告:
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 日]