[Back]

MacOS X Developer Preview 4 Release Notes Copyright © 2000 by Apple Computer, Inc. All Rights Reserved.

Mac OS X Developer Preview 4 Release Notes:
CoreFoundation Framework

CoreFoundation is a new framework in Mac OS X which provides consistent and powerful C APIs for strings, collections, user preferences, property lists, plug-ins, application and shared library packages, and XML handling, based on functionality available in the Cocoa Foundation framework and Carbon. These APIs are designed with portability, performance, and consistency in mind, and are available to Cocoa and Carbon applications on MacOS X and Carbon applications on Mac OS 8/9.


Notes Specific to Mac OS X Developer Preview 4

Changes in Mac OS X Developer Preview 4 from Preview 3

CFBundle

The following CFBundle APIs are new:

CFTypeRef CFBundleGetValueForInfoDictionaryKey(CFBundleRef bundle, CFStringRef key);

This returns a localized value for an info dictionary key from InfoPlist.strings if one is available, and the non-localized value from the Info.plist otherwise.

CFURLRef CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle);

CFURLRef CFBundleCopySharedFrameworksURL(CFBundleRef bundle);

CFURLRef CFBundleCopySharedSupportURL(CFBundleRef bundle);

CFURLRef CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle);

These functions return URLs for various locations within the bundle.

Boolean CFBundleGetPackageInfoInDirectory(CFURLRef url, UInt32 *packageType, UInt32 *packageCreator);

This returns TRUE and returns by reference the type and creator from the PkgInfo file, if they are available; otherwise it returns FALSE.

SInt32 CFBundleOpenBundleResourceFiles(CFBundleRef bundle, short *refNum, short *localizedRefNum);

This function opens (read-only) and makes current the non-localized and then the localized Resource Manager-style resource files (if available) for the bundle, and returns reference numbers for them. If it is called multiple times, it opens the files multiple times, and returns distinct reference numbers. Note that when an application is launched, this is done automatically so that the application's resources will always be available. For bundles other than the main bundle, this function would have to be called explicitly.

This function looks for the bundle's localized Resource Manager-style resources in the data fork of a file called Localized.rsrc in the appropriate .lproj directory. It looks for the bundle's non-localized Resource Manager-style resources in the data fork of a file called .rsrc, stored with other non-localized resources, where is the name of the bundle's main executable. For backward compatibility, if this file does not exist, it will also look in the resource fork of the bundle's main executable.

A bundle can always contain other Resource Manager-style resource files, which could be located using (for example) CFBundleCopyResourceURL, and then opened using Resource Manager calls. The CFBundleOpenBundleResourceFiles function will simply do all of this conveniently for you for one specific set of files.

Using the Debug Version of CoreFoundation

The standard version of CoreFoundation in general does not check for programming errors such as bad parameters, out of bounds indexing, invalid mutations, etc. The debug version, on the other hand, does, and it's a good idea to run against the debug version of CF whenever you suspect a CF or CF usage problem.

Rather than moving binaries around or rebuilding a "debug" version of your app, you can now do this easily from the command line by setting the environment variable DYLD_IMAGE_SUFFIX to the string "_debug" (without the quotes) in your shell, then running the program from that shell.

This instructs the dynamic loader (dyld) to load _debug versions of libraries whenever it finds them, instead of the standard versions. Basically what happens is the specified string is appended to library names as an optional suffix.

Changes to CFXMLParser

CFXMLParser's API has changed extensively since DP3. The CFXMLDataTypeDescription structure has been replaced by a new CFType, CFXMLNode. All the callbacks and functions which used to pass CFXMLDataTypeDescriptions have been changed accordingly. To reflect this change, the parser's version has been increased to 1; passing a version of 0 will now cause parser creation to fail. Please see the headers CFXMLParser.h and CFXMLNode.h for details.

CFPreferences

CFPreferences now stores application preferences under the application's bundle identifier, instead of the application's name. This is to prevent conflicts between different applications with the same name; if the bundle identifier has not been set, preferences will be stored under the application's name as before. For more on the bundle identifier, see /System/Documentation/Developer/ReleaseNotes/InfoPlist.html.

Run Loop API Changes

There have been several changes to the API in CFRunLoop.h. The DP3 CoreFoundation release notes warned of these changes. Obsolete functions will be removed after DP4. Programs which use these functions, or their new equivalents, will NOT be binary compatible with the next release of Mac OS X. Normally, Carbon programs should be using the Carbon event APIs, and Cocoa programs the Cocoa event APIs, instead of using CFRunLoop directly.

To convert to the new CFRunLoop APIs, you must #define CFRUNLOOP_NEW_API before the header #include directives in each source file in which the old APIs were used.

Changes in Mac OS X Developer Preview 3 from Preview 2

CFPreferences

We have added new API to CFPreferences to support framework and suite developers. First, we have added the constant kCFPreferencesCurrentApplication; frameworks can pass this constant in place of the application's name to retrieve preferences for the currently running application.

Secondly, we have made it possible for suites and frameworks to add their preferences to an application's preferences. To add your suite preferences, call CFPreferencesAddSuitePreferencesToApp(), passing the application's name (or kCFPreferencesCurrentApplication for the currently running application) and the name of your suite preferences. You can later remove your preferences by calling CFPreferencesRemoveSuitePreferencesFromApp() if you wish. Finally, set preferences for your suite by calling CFPreferencesSetValue(), passing your suite's name in place of the application name. The user name and host name arguments are as for applications; typically, you will pass a user name of kCFPreferencesCurrentUser and a host name of kCFPreferencesAnyHost.

RunLoop

There are some future changes to the operating system coming which may necessitate some changes in the CFRunLoop API. Specifically, the set of activities for observers in the CFRunLoopActivity enum type, and when observers are "fired" relative to the run loop's activities, may change.

Also, the behavior of of the CFRunLoopRunInMode() function may change, along with its return type. CFRunLoopRunInMode() currently returns after one source is processed. In the future, it may not return unless the run loop is specifically aborted. For highest performance, it is advantageous to remain in the run loop and handle callouts from it as events occur rather than exiting from the run loop and then handling an event outside of the run loop context.

Finally, there are some planned API changes which will probably happen after DP3:

CFByteOrder API changes

There have been some significant changes to the CFByteOrder.h API. See the documentation for an overview of the new API. The following tops script will allow you to use the tops command-line tool to autoconvert your code if you have heavy usage of CFByteOrder API. You can also read the list below to determine the mapping from old to new names for hand-conversion.

Note particularly that the usage of float and double swapping has changed. You no longer explicitly swap floats and doubles, but rather convert them to and from an opaque CFSwappedFloat32 or CFSwappedFloat64 type using the new API. A CFSwappedFloat has the specified bit-length and is in some canonical, but unspecified, format maintained by the CFByteOrder API.

replace "CFUnknownByteOrder" with "CFByteOrderUnknown"
replace "CFLittleEndian" with "CFByteOrderLittleEndian"
replace "CFBigEndian" with "CFByteOrderBigEndian"
replace "CFHostByteOrder" with "CFByteOrderGetCurrent"

replace "CFSwapBigInt16ToHost" with "CFSwapInt16BigToHost"
replace "CFSwapBigInt32ToHost" with "CFSwapInt32BigToHost"
replace "CFSwapBigInt64ToHost" with "CFSwapInt64BigToHost"
replace "CFSwapHostInt16ToBig" with "CFSwapInt16HostToBig"
replace "CFSwapHostInt32ToBig" with "CFSwapInt32HostToBig"
replace "CFSwapHostInt64ToBig" with "CFSwapInt64HostToBig"
replace "CFSwapLittleInt16ToHost" with "CFSwapInt16LittleToHost"
replace "CFSwapLittleInt32ToHost" with "CFSwapInt32LittleToHost"
replace "CFSwapLittleInt64ToHost" with "CFSwapInt64LittleToHost"
replace "CFSwapHostInt16ToLittle" with "CFSwapInt16HostToLittle"
replace "CFSwapHostInt32ToLittle" with "CFSwapInt32HostToLittle"
replace "CFSwapHostInt64ToLittle" with "CFSwapInt64HostToLittle"

replace "CFSwappableFloat32" with "CFSwappedFloat32"
warning "CONVERSION: check usage of this CFSwappedFloat32-typed variable"
replace "CFSwappableFloat64" with "CFSwappedFloat64"
warning "CONVERSION: check usage of this CFSwappedFloat64-typed variable"
replace "CFConvertHostFloat32ToSwappable" with "CFConvertFloat32HostToSwapped"
warning "CONVERSION: check usage of the CFConvertFloat32HostToSwapped function"
replace "CFConvertSwappableFloat32ToHost" with "CFConvertFloat32SwappedToHost"
warning "CONVERSION: check usage of the CFConvertFloat32SwappedToHost function"
replace "CFConvertHostFloat64ToSwappable" with "CFConvertFloat64HostToSwapped"
warning "CONVERSION: check usage of the CFConvertFloat64HostToSwapped function"
replace "CFConvertSwappableFloat64ToHost" with "CFConvertFloat64SwappedToHost"
warning "CONVERSION: check usage of the CFConvertFloat64SwappedToHost function"

replace "CFSwapBigFloat32ToHost" with "CFSwapBigFloat32ToHost"
error "CONVERSION: the CFSwapBigFloat32ToHost function has been removed from the API"
replace "CFSwapBigFloat64ToHost" with "CFSwapBigFloat64ToHost"
error "CONVERSION: the CFSwapBigFloat64ToHost function has been removed from the API"
replace "CFSwapHostFloat32ToBig" with "CFSwapHostFloat32ToBig"
error "CONVERSION: the CFSwapHostFloat32ToBig function has been removed from the API"
replace "CFSwapHostFloat64ToBig" with "CFSwapHostFloat64ToBig"
error "CONVERSION: the CFSwapHostFloat64ToBig function has been removed from the API"
replace "CFSwapLittleFloat32ToHost" with "CFSwapLittleFloat32ToHost"
error "CONVERSION: the CFSwapLittleFloat32ToHost function has been removed from the API"
replace "CFSwapLittleFloat64ToHost" with "CFSwapLittleFloat64ToHost"
error "CONVERSION: the CFSwapLittleFloat64ToHost function has been removed from the API"
replace "CFSwapHostFloat32ToLittle" with "CFSwapHostFloat32ToLittle"
error "CONVERSION: the CFSwapHostFloat32ToLittle function has been removed from the API"
replace "CFSwapHostFloat64ToLittle" with "CFSwapHostFloat64ToLittle"
error "CONVERSION: the CFSwapHostFloat64ToLittle function has been removed from the API"
replace "CFSwapFloat32" with "CFSwapFloat32"
error "CONVERSION: the CFSwapFloat32 function has been removed from the API"
replace "CFSwapFloat64" with "CFSwapFloat64"
error "CONVERSION: the CFSwapFloat64 function has been removed from the API"

CFUUID

The missing function CFUUIDGetTypeID() has been added to the header.

CarbonCore Linkage

CoreFoundation no longer links with CarbonCore framework directly, but rather loads it dynamically when functionality in CoreFoundation which needs it is first used. If you were linking with CoreFoundation only previously, but using CarbonCore symbols, you will need to link with CarbonCore explicitly now as well. Also, although no longer explicitly linking with CarbonCore, CarbonCore symbols will still be part of the runnning process's address space if it's dynamically loaded, so symbol collisions can still result, as noted in a note below.


Changes in Mac OS X Developer Preview 2 from Preview 1

Property Lists

The new function CFPropertyListCreateDeepCopy() can be used to make deep copies (mutable or immutable) of property lists.

Socket

CFSocketRef has been added to CoreFoundation. It encapsulates a native socket (of arbitrary type and protocol) so that it can read from the socket in the background and make the results available using a CFRunLoopSource. There are three ways in which this can be used: one in which the source provides the data read to the client in a CFData; one in which the source merely signals the availability of data, leaving it to the client to read it; and one in which the CFSocket accept()s new connections and the source provides them to the client. A CFSocket can also be used to write data to the socket with a timeout.

Tree

CFTreeRef has been added, primarily in support of CFXMLParser. However it can be used by itself as well.

Preferences

There is a known bug in CFPreferencesCopyApplicationList(), where the domain "any application" is reported both as "kCFPreferencesAnyApplication" (correct) and as "*" (incorrect). You can see the effects of this by executing "defaults domains" from within Terminal - the domain "*" will be listed in addition to the global domain. We ask developers to work around this by manually filtering "*" from the list of applications returned. This is fixed in DP3.

Allocator

There is now a new built-in allocator, kCFAllocatorMalloc. It uses the standard malloc() functions to do its allocations.

PlugIn

CFPlugIn now uses a more COM-like model to find and identify plug-ins. To support this functionality, a new type, CFUUIDRef, was added to CoreFoundation.

The previous mechanism (where strings were used) is still supported for binary-compatibility reasons, but recompiling will lead to warnings as the CFPlugIn functions are now declared in terms of CFUUIDRef. Please refer to the CFBundle/CFPlugIn release note for details.

CarbonLib

CFBundle, CFPlugIn, CFURL, and CFUUID are now available to Carbon applications on MacOS 9 and earlier systems where CarbonLib is shipped. Generalized XML parsing and related functionality will soon be added to this list.

Note that some CoreFoundation APIs are not planned to ever be available on CarbonLib. These include CFRunLoop, CFSocket, CFNotification.

CFM-based applications on Mac OS X also only have access to the APIs that are common subset of APIs available on both platforms. Full CoreFoundation functionality is available to Mach-O Carbon applications running on MacOS X.

URL and HFS paths

There is a known bug in CFURL's handling of HFS paths; the HFS volume does not get properly translated to the equivalent POSIX mount point and vice versa. The effect is that URLs constructed via CFURLCreateWithFileSystemPath() with a pathStyle of kCFURLHFSPathStyle will not be properly constructed, and will not return reliable results when further CFURL function calls are made with the resulting CFURL. Likewise, CFURLGetFileSystemPath() is unreliable when passed a pathStyle of kCFURLHFSPathStyle. We ask developers to work around this by converting the HFS path to a POSIX path themselves, then creating the CFURL from the POSIX path. This is fixed in DP3.

Carbon

CoreFoundation now links against the low-level Carbon library (CarbonCore), which means that the public symbols in this library appear in the same name space as CoreFoundation. Most of the public symbols in Carbon do not use prefixes, which makes it possible for there to be symbol conflicts. The solution to this is to avoid the conflicts by renaming your symbols.

General Notes

Property Lists

CFPropertyLists have been extended to include CFDate, CFNumber, and CFBoolean (extended from Foundation-style property lists); this makes the complete list of property list types CFArray, CFBoolean, CFData, CFDate, CFDictionary, CFNumber, and CFString. Please note that, although all these types are bridged between CF and the Foundation class equivalents, the Foundation methods that read property lists will silently fail (returning nil) if one of the new types are detected - this is to ensure compatibility with Foundation clients that are not prepared to handle the new types.

XML Parsing

Generalized XML handling has been added through CFXMLParser. There are still some parse options that are not supported. These are kCFXMLParserValidateDocument, kCFXMLParserReplacePhysicalEntities, and kCFXMLParserAddImpliedAttributes. Please see the comments in CFXMLParser.h for further details.

There is a known bug in CFXMLCreateDataTypeDescriptionCopy(). If the description to be copied contains a NULL URL, CFXMLCreateDataTypeDescriptionCopy() tries to retain it, thereby crashing the program. Unfortunately, this will occur if CFXMLTreeCreateFromData() is called with a NULL dataSource argument. This can be worked around by providing any valid, non-NULL CFURL as the data source. This will be fixed in the first release after Developer Preview 3.

String

Please keep in mind that whether or not CFStringGetCStringPtr() and CFStringGetPascalStringPtr() return NULL might change between various releases of the CoreFoundation. These functions are provided for optimization purposes, and if they return NULL your code should fall back to the other functions which will return a value (if there is a value). See comments in CFString.h for details.

We reemphasize this point as some internal performance changes in CFString could lead to these functions returning NULL more often in some cases (and less in others).

Debug Library

The CoreFoundation ships with a debug version of the binary. If you build your project with the "debug" target, it should be linked to the debug CoreFoundation binary.

The debug binary contains debugging assertions and other checks to aid in project development. The debug binary is provided because the ordinary production binary for CoreFoundation does little or no checking at all, and in general does whatever you tell it to do, even if that is obviously wrong. For example, you can tell a CFArray to remove the value at index -1 (valid indices are non-negative from 0 to generally one less than the number of values in the array), and CFArray will do that -- however, that operation has now corrupted memory. If you are running with the debug CoreFoundation library, an assertion will catch this and a message will be printed out and the program terminated.

Note that the use of debugging assertions is not totally wide-spread yet. We plan to introduce more assertions throughout CoreFoundation as the opportunity comes up.

"Toll-free" Bridging with Foundation classes

See the Foundation Release Notes for information on the toll-free bridging between some CF types and Foundation classes. Types that are toll-free bridged (for instance, NSString and CFStringRef) can be used interchangeably in all APIs accepting either type.

CoreFoundation Examples

There are some CoreFoundation examples in /System/Developer/Examples/CoreFoundation. These compile and run on DP3. There are also CodeWarrior project files in those directories; however, those do not work as-is. You will need to remove references to InterfaceLib and MathLib; pull in CarbonLib and Carbon compatible SIOUX library, and also add {Compiler}:MacOS Support:Headers:Universal Headers: to your header path before the examples can be compiled on Mac OS 9.