Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Q&As > Carbon > Interapplication Communication >

Retrieving Data from AEDesc Records - do not use the dataHandle field


Q: How should I retrieve the data stored in an Apple event descriptor record?

A: You cannot use direct memory access to retrieve the data associated with an Apple event descriptor record using the Carbon Apple Event Manager APIs. Apple provides two Carbon accessor APIs (AEGetDescDataSize and AEGetDescData) that allow you to retrieve a copy of the data stored in an AEDesc structure. Appropriate use of these two APIs is illustrated in Listing 1.



Listing 1. Using AEGetDescDataSize and AEGetDescData to retrieve a copy of the data stored in an AEDesc record.

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

    ....

    /* find out the length of the data stored
    in the descriptor record */
theLength = AEGetDescDataSize(&theDesc);

    /* allocate a buffer to hold a copy
    of the data */
theData = malloc(theLength);
if (theData != NULL) {

        /* copy the data to the buffer */
    err = AEGetDescData(theDesc, theData, theLength);
    if ( err == noErr) {

        /* perform some operation with the
        extracted data */

        ....


To change the data stored in an AEDesc record, applications can use the routine AEReplaceDescData.



IMPORTANT:
The AEGetDescData, AEGetDescDataSize, and AEReplaceDescData routines can only be used with descriptors that store simple values - they cannot be used with compound descriptor record types such as AppleEvent records, AERecord records, and AEDescList records. Attempting to use these routines with compound descriptor record types may produce unexpected results or even application crashes.



Background

AEDesc structures contain two components: a descriptor type field and a data field. The descriptor type field contains a thirty-two bit code (often four ASCII letters) identifying the type of data stored in the descriptor record. The data field is used internally by the Apple Event Manager to store a reference to the data associated with the descriptor record. Listing 2 shows the declaration for an AEDesc structure.



Listing 2. AEDesc structure declaration.

typedef AEDataStorageType *AEDataStorage;

struct AEDesc {
    DescType       descriptorType; /* the data type field */
    AEDataStorage  dataHandle;     /* the data field */
};


Implementations of the Apple Event Manager in versions of the Mac OS prior to Mac OS X used the dataHandle field to store the information associated with an AEDesc record in a block of memory referred to by a Carbon Memory Manager Handle. But, with the advent of the Carbon APIs and Mac OS X, the dataHandle field in the AEDesc structure was changed to an opaque pointer type. With that change, it became inappropriate for software to make assumptions about the meaning of the contents of this field.



WARNING:
Code that uses the value stored in the dataHandle field in an AEDesc structure or assumes that the dataHandle field contains a Carbon Memory Manager Handle is not supported and may not work in future implementations of the Apple Event Manager in Mac OS X.



The AEDesc structure itself is not opaque. As such, it is possible for application software to access the descriptorType field to determine the type of data stored in the AEDesc record. Applications should not make any assumptions about the meaning of the value stored in the dataHandle field. For best results, developers should structure their code so that it does not depend on, or make any assumptions about, the contents of the dataHandle field (as shown in Listing 3).



Listing 3. Sample of structuring code so it does not use the value stored in the dataHandle field of an AEDesc record.

    AEDesc theDesc;
    char* p = "Hello World";

        /* create the descriptor */
    err = AECreateDesc(typeChar, p, strlen(p), &theDesc);
    if (err == noErr) {

        /* perform some operations using
        the descriptor */

            /* delete the descriptor */
        AEDisposeDesc(&theDesc);
    }


The Exception to the Rule

It is okay for code to compare the dataHandle field to NULL to determine whether the AEDesc record has any data associated with it, as shown in Listing 4. However, it does not make sense to use the dataHandle field in any other way.



Listing 4. Examples of code that makes safe assumptions about the dataHandle field in and AEDesc record.

AEDesc d = { typeNull, NULL };  // Initialize a new empty descriptor

if (d.dataHandle != NULL)  // A cheap check for a non-empty descriptor



[Apr 10 2002]