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]
|