TweetFollow Us on Twitter

Counting To X

Volume Number: 15 (1999)
Issue Number: 3
Column Tag: ExplainIt

Counting to X

by Dave Evans and Mark Turner

Ten Steps Toward Carbon Compatibility

Carbon is the basic element in Apple's plan to take Mac OS applications into the next millennium. Together with Mac OS X, Carbon delivers exactly what developers have been asking for -; an easy way of allowing Mac applications to enjoy all the advantages of a memory protected, preemptively scheduled, multitasking operating system.

A preliminary version of the Carbon SDK has already been released to members of the Apple Developer Program, but even if you're not a member, there's a lot you can do now to make your transition to Mac OS X easier. And the good news is that these changes will also provide a better experience for your customers running Mac OS 8. In this article we'll discuss ten steps you can take to prepare for Carbon. But first, a brief overview of Carbon and why it's important that you prepare for it now.

Carbon Defined

Carbon is a set of APIs that run on both Mac OS 8 and Mac OS X. It's a hybrid that includes over 70 percent of the existing Mac OS APIs, covering about 95 percent of the functions used by applications. Because it includes most of the functions you rely on today, converting to Carbon is relatively painless. And by weeding out or modifying certain difficult-to-support functions, Carbon provides a more streamlined and stable base for application development.

What this means for you is that by making a small investment in Carbon, your programs will gain these benefits when running under Mac OS X:

  • Greater stability.
    Preemptive multitasking and protected address spaces will help prevent other people's bugs from crashing your application. (It goes without saying that there are no bugs in your code!)
  • Improved responsiveness.
    Because all applications are guaranteed processing time through preemptive scheduling, you don't have to worry about being locked out by another program that's hogging the CPU. And since Mac OS X and Carbon are 100% PowerPC native, there's no 68K emulation and no mode-switching overhead to slow down your applications.
  • Efficient use of system resources.
    Your application isn't limited to a fixed heap size and can dynamically allocate memory and other system resources based on actual needs rather than predetermined values.

Although your current applications will continue to run unmodified in Mac OS X through a technology code-named the Blue Box, they won't enjoy all the performance and reliability enhancements of Mac OS X until you update them for Carbon.

That all sounds great, but the best part is that you don't have to wait for Mac OS X to appreciate the benefits of Carbon. By cleaning up old code and adopting Carbon-compatible APIs, your applications will run more reliably on today's Mac OS while taking advantage of the latest Apple technologies and human interface improvements.

Nothing's free in this world, and Carbon is no exception. It'll cost you about two weeks work to update a typical application. But by preparing for Carbon now, your applications will not only run better on Mac OS 8, they'll be ready to rock when Mac OS X rolls out later this year.

Carbon Coding

Okay, time to roll up your sleeves, fire up your Mac, and give your app a tune-up.

I. Read the Carbon Paper

Before you change a single line of code, you should read Transitioning to Mac OS X: An Overview of the Carbon Programming Interface. This white paper explains why Carbon is so important, and defines Apple's goals for the project. It also lists the expected level of support for all existing Mac OS APIs. You'll find the Carbon Paper, and a lot of other helpful information, on the Carbon web site at http://developer.apple.com/macosx/carbon/.

While you're visiting the web site, be sure to check out the official Carbon Specification for the most up-to-date list of supported APIs. Then download the Carbon Dater tool, because we're going to talk about it next.

II. Run Carbon Dater

If you completed Step I, you already know that Apple's Carbon Dater tool provides a detailed report of your code's current Carbon compliance level. (If you didn't follow Step I, shame on you! Go back and read the Carbon Paper.) Carbon Dater works by examining PEF containers in application binaries and CFM libraries. It compares the list of Mac OS symbols your code imports against Apple's database of Carbon-supported functions and issues a spiffy report formatted in HTML.

In addition to analyzing your Mac OS function calls, Carbon Dater tries to identify any attempts to read or write directly to low-memory, and it also reports if any of your resources have the system heap bit set. Carbon applications don't have access to the system heap in Mac OS X, so you can't load resources there.

As we discuss in Step IV, all access to low-memory system global data must be through accessor functions. Because many of today's accessor functions are simply macros that implement a load or store to memory, Carbon Dater can't determine if your low-memory accesses are illegal -; it's up to you to make sure you're using the proper functions.

Apple is working very hard to make the Carbon transition an easy one, and the Carbon Dater statistics bear this out. As Figure 1 shows, of the thousands of applications tested, the average compliance level is over 95 percent.


Figure 1. Carbon Dater Results

For step-by-step instructions on running Carbon Dater and interpreting the results, see the Getting Started column, Carbon: Getting Ready for Mac OS X, in the January 1999 issue of MacTech.

III. Use the Most Recent Universal Headers

Okay, so you've read up on Carbon, tested your application, and most likely discovered that it's pretty close to 95 percent compatible. What do you do next? Sync up with the latest Universal Header files!

You can start by downloading the current headers from Apple's web site. As of this writing, Apple has released version 3.2 of the Universal Headers, incorporating all the new technologies in Mac OS 8.5. In addition to new APIs, there are minor changes from previous 3.x versions. For example, the KeyMap definition has changed from an array of longs to an array of Uint32 values. Be sure to read the release notes for more information about what has changed.

After successfully building your application on the current headers, you should download and install the Carbon headers. The Carbon headers incorporate additional changes, including new conditionals to use when building Carbon applications and new APIs to replace some of the older functions that aren't supported in Carbon.

The Carbon headers eventually will be rolled into future versions of the Universal Headers, and you can use them for building non-Carbon applications today. To build a Carbon application, just add the following statement to one of your source files before including any of the Carbon headers:

#define TARGET_CARBON 1

The TARGET_CARBON conditional specifies that the included header files should allow only Carbon-compatible APIs and data structures. When you throw this switch and rebuild, you're likely to get a number of errors and warnings from the compiler. For now, stifle the urge to hack your way through those errors. You'll save yourself a lot of time if you read the rest of this article and address each issue methodically.

IV. Avoid Using Low-Memory Globals

Low-memory globals are system and application global data located below the system heap in Mac OS 8. They typically fall between the hexadecimal addresses $100 and $2800. Since the transition to PowerPC, Apple has provided accessor routines for getting and setting these global variables. Prior to that, you would simply dereference the absolute address of the global to modify it.

Carbon applications still have access to many of the low-memory globals, although in some cases the scope and impact of the global has changed. But in all cases, Carbon applications must use the supplied accessor routines to examine or change global variables. Attempting to access them directly with an absolute address will crash your application when running on Mac OS X.

The complete list of low-memory globals supported in Carbon hasn't been published yet, but you'll be better prepared if you take the time now to review your use of low memory. The transition to Carbon will be easier if you follow these guidelines:

  • Use high-level Toolbox calls instead of low-memory accessors whenever possible.
  • If a high-level call is not available, use an accessor function.
  • Rely on global data only from Toolbox managers supported in Carbon.

Make your best guess about the last point until Apple publishes a definitive list. For example, because the driver-related calls in the Device Manager are not supported in Carbon, low-memory accessors like LMGetUTableBase are not likely to be available. Similarly, direct access to hardware is not supported in Carbon, so calls like LMGetVIA will no longer be useful.

Some low-memory accessors have Toolbox equivalents -; applications must switch to these Toolbox calls instead. For example, use GetMouse instead of LMGetMouse, Ticks instead of LMGetTicks, and MemError instead of LMGetMemErr.

V. Go Native

Because Carbon requires 100% native PowerPC code, you must remove any dependencies on 68K instructions. Unless you have written your application entirely in assembly language, this should not be a big issue for your main application code. Where you are more likely to have 68K code is in custom definition procedures (defprocs) and plug-ins.

Custom defprocs (for example, MDEFs, CDEFs, and LDEFs) must be compiled as PowerPC code and no longer can be stored in resources. Carbon will introduce new variants of CreateWindow and similar calls (NewControl, NewMenu, etc.) that will take a universal ProcPtr for a definition procedure. Instead of providing a WDEF in a resource, you would instead call a new Toolbox routine that might look something like this:

OSStatus CreateCustomWindow(WindowClass windowClass, 
      WindowAttributes attributes, const Rect *bounds, 
      WindowDefUPP customProc, WindowPtr *outWindow);

For all Mac OS functions that expect definition procedures in resources today, there will be new routines to specify the custom procedure. But before you spend a lot of time updating old defprocs, you should think about whether there is any need to continue rolling your own interface elements. New APIs like the Appearance Manager and Navigation Services may provide all the features you want.

That said, if you want to compile custom defprocs into your code today, the following snippet shows a clever way to do it. This will not work in the future for Carbon applications on Mac OS X, but for a Mac OS 8 application, it will allow defprocs in native code using stub routines as shown here.

// Using a 6-byte stub WDEF resource (ID 128 for example),
// fill in a 680x0 'jmp' opcode and the address of a UPP
// to the native definition proc. Note: NewWindowDefProc
// will allocate memory in Mac OS 8.x

Handle theStub;
theStub = GetResource('WDEF', 128);
if (theStub && *theStub)
{
   WindowDefUPP theProcUPP;

   theProcUPP = NewWindowDefProc(&MyWDEF);
   *((long *) (*theStub + 2)) = theProcUPP;
   *((short *) *theStub) = 0x4EF9;

   // We just modified code, flush the emulator cache
   FlushCodeCacheRange(*theStub, 6);
}

VI. Get Used to Opaque Toolbox Data Structures

Some familiar Toolbox data structures are not directly accessible in Carbon. There are new functions to inspect the contents of these opaque structures. For example, you can no longer dereference a CGrafPtr to inspect the contents of the GrafPort structure. Instead of addressing a port bounds rectangle directly with &myport->bounds, you must call the new routine GetPortBounds(myport, &myrect) with a local variable for the result. For each accessible element of an opaque data structure there is a corresponding new routine for getting or setting that element.

Supporting opaque Toolbox structures likely will take some work in your code. To begin with, you probably will have to create new local variables for return results. Almost all accessor functions return a copy of the data and not a pointer to the actual data. This passing of data by value instead of by reference requires that you allocate space for results either in memory or as local variables on the stack. For efficiency, you should place calls to accessors strategically in your code and use them minimally.

Window records are opaque in Carbon, and are not just extended versions of GrafPorts. Windows and ports are no longer synonymous, and code that treats them interchangeably will crash on Mac OS X. For example, the following statement casts a WindowPtr to a GrafPtr:

SetPort( (GrafPtr) myWindow );          // don't do this!

Look familiar? Code like this will cause you grief in the future because your program will compile and run just fine on Mac OS 8 but crash on Mac OS X. The right way to get the port for a window is with the GetWindowPort function, like this:

SetPort( GetWindowPort( myWindow ));   // do this instead

Another practice to avoid is hanging your own data off the end of Toolbox structures. For example, because the internal representation of a window record is no longer visible, you can't save private data by adding it to the end of the window record and passing a pStorage value to NewWindow. In Carbon, you must pass NULL in the pStorage field. If you need extra storage for windows, keep a reference to your data in the refCon field. If you are currently using pStorage in this way, switching to refCon is something you can do today to prepare for Carbon.

The upside to these changes is that Apple can take steps to ensure that the internal representation of data is aligned in memory for fastest access, and new elements can be added for Carbon-specific features. With opaque data structures in Carbon, the Toolbox easily can be extended in the future.

Not all data structures are opaque in Carbon, though. TextEdit data in a TERecord, for example, still is directly accessible. The Apple Event AEDesc structure also is directly accessible, but the type of the dataHandle in the structure is opaque. Some data structures were not made opaque because they're so simple, like the AEDesc structure, and others because the Toolbox component is not expected to change in the future. This is why the TERecord is not opaque, as TextEdit will be replaced outright by a Unicode aware text engine.

VII. Adopt Supported Technologies

A number of Mac OS functions are not being carried forward in Carbon. For these you must adopt Apple's suggested replacement functions or find other ways of accomplishing those functions. Carbon is a work in progress, and you may run across a few APIs that are listed as unsupported in Carbon but for which replacement APIs or workarounds are not yet defined. If you feel strongly that Apple should support an API that is listed as unsupported or under evaluation in the Carbon Specification, make your voice heard by sending e-mail to <carbon@apple.com>.

Three important Carbon-supported technologies that you should adopt today are the Appearance Manager, Navigation Services, and Open Transport. The Appearance Manager coordinates the look and feel of the Mac OS human interface and provides a rational and supported API for adding custom interface elements.

Navigation Services replaces the venerable Standard File Package, and is shipping now in Mac OS 8.5. Using sample code provided in the Navigation Services SDK (available on Apple's web site), we were able to replace all the Standard File calls in AppleWorks in one day. You also should read Keith Mortensen's excellent article on the subject in the August 1998 issue of MacTech.

Open Transport replaces MacTCP and classic AppleTalk in Carbon. If you have not already adopted OT, now is definitely the time. First introduced in System 7.5.2, Open Transport has evolved into a mature, efficient, and extensible networking architecture capable of saturating 100Mbit Ethernet.

VIII. Don't Patch Traps

You cannot patch traps in Mac OS X for one simple reason: there is no trap table. Because the operating system is PowerPC native, no 68K trap table is needed. Unlike Mac OS 8, most calls to Mac OS X Toolbox functions are implemented as a jump directly to the specified routine. In Mac OS 8 you can patch traps to intercept Toolbox calls and modify their behavior, but with no central dispatch mechanism to hook into, this is not possible in Mac OS X.

Consequently, GetTrapAddress, SetTrapAddress, and related functions are not available in Carbon. You can, of course, conditionalize your code and continue to patch traps when running under Mac OS 8, but your programs will be much easier to maintain if you avoid patching entirely.

Apple is considering a variety of mechanisms to allow programmatic extensibility. The goal is to provide you with system-level APIs for altering certain default behaviors. If you have suggestions or specific requirements that you would like Apple to support, send them to <carbon@apple.com>.

For now you should take a close look at any trap patches in your code and ask yourself if they could be replaced with another approach. Instead of patching ExitToShell, for example, try using a CFM termination proc for your main fragment.

IX. Draw Only Within Your Own Windows

Because Mac OS X is a truly preemptive system, any number of applications may be drawing into their windows at the same time. And of course, a user may be dragging a window or other object around the screen while background applications are drawing in their windows. In order to make all this work, Carbon applications must play by these rules:

First, you should no longer try to draw outside of your windows. In the past you could call the GetWMgrPort function and use that port to draw anywhere on the screen. This port no longer exists in Mac OS X. If you were using this technique for custom dragging or zooming feedback, use DragWindow or other Drag Manager functions instead.

Second, if you draw directly into the bitmap of your windows (without using QuickDraw) you must wrap those blits with two new calls that will tell the Window Manager to get out of the way. We are still working on these functions, so for now you might just want to insert some comments to remind you that you eventually must update this kind of code for Carbon.

X. Manage Memory Efficiently

Memory management does not change much for Carbon applications running on Mac OS 8. You will need all the code you use today to manage heap fragmentation, low memory situations, and stack depth.

However, there are some things you must do to perform well when running in a Mac OS X environment. In that world, your application will run in a very different heap structure with different allocation behavior. Your memory will not tend to move as much and your stack will be far away from your heap, with guard pages below it. The most significant change you must make is in determining amounts of free memory and stack space available.

In the future, when your Carbon application is intended to run only on Mac OS X, you will be able to take full advantage of new memory behavior. You might switch from handle-based to pointer-based allocations, for example. But as long as your application runs on Mac OS 8, you should prepare for the same issues you always have.

The functions FreeMem, PurgeMem, MaxMem, and StackSpace are all available in Carbon. You should, however, think about how and why you are using them. You will probably want to consider additional code to better tune your performance.

The FreeMem, PurgeMem, and MaxMem functions behave as expected when your Carbon application is running on Mac OS 8, but they are almost meaningless when it is running on Mac OS X, where you have essentially unlimited virtual memory. Although you can still use these calls to ensure that your memory allocations will not fail, you should not use them to allocate all available memory. Allocating too much virtual memory will cause excessive page faults and reduce system performance. Instead, determine how much memory you really need for your data, and allocate that amount.

Before Carbon you would use the StackSpace function to determine how much space was left before the stack collided with the heap. This routine could not be called at interrupt time, but was useful for preventing heap corruption in code using recursion or deep call chains. But, since a Carbon application may have different stack sizes under Mac OS 8 and Mac OS X, the StackSpace function is no longer very useful. You should not rely on it for your logic to terminate a recursive function. It might still be useful as a safety check to prevent heap corruption, but for terminating runaway recursion you should consider passing a counter or the address of a stack local variable instead of calling StackSpace.

The Carbon API does not include any subzone creation or manipulation routines. If you use subzones today to track Toolbox or plug-in memory allocations, you will have to use a different mechanism. For plug-ins, you might switch to using your own allocator routines. To prevent leaks of Toolbox data, make sure all Toolbox allocations are matched with the appropriate dispose calls.

The Carbon API also removes the definition of zone headers. You no longer can modify the variables in a zone header to change the behavior of Toolbox routines like MoreMasters. Simply call MoreMasters multiple times instead, which will allocate 128 master pointers each time.

Summary

Everything you do now to make your application run great on Mac OS 8 is a step toward Carbon compatibility. Adopting the Appearance Manager, Navigation Services, and Open Transport is a great way to start. And by following the steps outlined in this article, your transition to Carbon will be that much easier.

While it has been our experience that a typical application can be "Carbonized" in a couple of weeks, a lot depends on how zealously you have followed Apple's programming recommendations in the past. If you have not cracked a copy of Inside Macintosh in a couple of years, or do not remember the last time you synchronized with Apple's latest header release, it might take you a bit longer to whip your code into shape. All the more reason to get started early!


Dave Evans is an engineer on the Carbon team and Mark Turner is a technical writer at Apple Computer.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Jump into one of Volkswagen's most...
We spoke about PUBG Mobile yesterday and their Esports development, so it is a little early to revisit them, but we have to because this is just too amusing. Someone needs to tell Krafton that PUBG Mobile is a massive title because out of all the... | Read more »
PUBG Mobile will be releasing more ways...
The emergence of Esports is perhaps one of the best things to happen in gaming. It shows our little hobby can be a serious thing, gets more people intrigued, and allows players to use their skills to earn money. And on that last point, PUBG Mobile... | Read more »
Genshin Impact 5.1 launches October 9th...
If you played version 5.0 of Genshin Impact, you would probably be a bit bummed by the lack of a Pyro version of the Traveller. Well, annoyingly HoYo has stopped short of officially announcing them in 5.1 outside a possible sighting in livestream... | Read more »
A Phoenix from the Ashes – The TouchArca...
Hello! We are still in a transitional phase of moving the podcast entirely to our Patreon, but in the meantime the only way we can get the show’s feed pushed out to where it needs to go is to post it to the website. However, the wheels are in motion... | Read more »
Race with the power of the gods as KartR...
I have mentioned it before, somewhere in the aether, but I love mythology. Primarily Norse, but I will take whatever you have. Recently KartRider Rush+ took on the Arthurian legends, a great piece of British mythology, and now they have moved on... | Read more »
Tackle some terrifying bosses in a new g...
Blue Archive has recently released its latest update, packed with quite an arsenal of content. Named Rowdy and Cheery, you will take part in an all-new game mode, recruit two new students, and follow the team's adventures in Hyakkiyako. [Read... | Read more »
Embrace a peaceful life in Middle-Earth...
The Lord of the Rings series shows us what happens to enterprising Hobbits such as Frodo, Bilbo, Sam, Merry and Pippin if they don’t stay in their lane and decide to leave the Shire. It looks bloody dangerous, which is why September 23rd is an... | Read more »
Athena Crisis launches on all platforms...
Athena Crisis is a game I have been following during its development, and not just because of its brilliant marketing genius of letting you play a level on the webpage. Well for me, and I assume many of you, the wait is over as Athena Crisis has... | Read more »
Victrix Pro BFG Tekken 8 Rage Art Editio...
For our last full controller review on TouchArcade, I’ve been using the Victrix Pro BFG Tekken 8 Rage Art Edition for PC and PlayStation across my Steam Deck, PS5, and PS4 Pro for over a month now. | Read more »
Matchday Champions celebrates early acce...
Since colossally shooting themselves in the foot with a bazooka and fumbling their deal with EA Sports, FIFA is no doubt scrambling for other games to plaster its name on to cover the financial blackhole they made themselves. Enter Matchday, with... | Read more »

Price Scanner via MacPrices.net

Apple Watch Ultra available today at Apple fo...
Apple has several Certified Refurbished Apple Watch Ultra models available in their online store for $589, or $210 off original MSRP. Each Watch includes Apple’s standard one-year warranty, a new... Read more
Amazon is offering coupons worth up to $109 o...
Amazon is offering clippable coupons worth up to $109 off MSRP on certain Silver and Blue M3-powered 24″ iMacs, each including free shipping. With the coupons, these iMacs are $150-$200 off Apple’s... Read more
Amazon is offering coupons to take up to $50...
Amazon has Apple’s M2-powered Mac minis in stock and on sale for up to $110 off MSRP, each including free delivery. Prices are valid after free coupons available on each mini’s product page, detailed... Read more
Use your Education discount to take up to $10...
Need a new Apple iPad? If you’re a student, teacher, or staff member at any educational institution, you can use your .edu email address when ordering at Apple Education to take up to $100 off the... Read more
Apple has 15-inch M2 MacBook Airs available f...
Apple has clearance, Certified Refurbished, 15″ M2 MacBook Airs available starting at $1019 and ranging up to $300 off original MSRP. These are the cheapest 15″ MacBook Airs for sale today at Apple.... Read more
Mac Studio with M2 Max CPU on sale for $1749,...
B&H Photo has the standard-configuration Mac Studio model with Apple’s M2 Max CPU in stock today and on sale for $250 off MSRP, now $1749 (12-Core CPU and 32GB RAM/512GB SSD). B&H offers... Read more
Save up to $260 on a 15-inch M3 MacBook Pro w...
Apple has Certified Refurbished 15″ M3 MacBook Airs in stock today starting at only $1099 and ranging up to $260 off MSRP. These are the cheapest M3-powered 15″ MacBook Airs for sale today at Apple.... Read more
Apple has 16-inch M3 Pro MacBook Pro in stock...
Apple has a full line of 16″ M3 Pro MacBook Pros available, Certified Refurbished, starting at $2119 and ranging up to $440 off MSRP. Each model features a new outer case, shipping is free, and an... Read more
Apple M2 Mac minis on sale for $120-$200 off...
Amazon has Apple’s M2-powered Mac minis in stock and on sale for $110-$200 off MSRP this weekend, each including free delivery: – Mac mini M2/256GB SSD: $469, save $130 – Mac mini M2/512GB SSD: $689.... Read more
Clearance 9th-generation iPads are in stock t...
Best Buy has Apple’s 9th generation 10.2″ WiFi iPads on clearance sale for starting at only $199 on their online store for a limited time. Sale prices for online orders only, in-store prices may vary... Read more

Jobs Board

Senior Mobile Engineer-Android/ *Apple* - Ge...
…Trust/Other Required:** NACI (T1) **Job Family:** Systems Engineering **Skills:** Apple Devices,Device Management,Mobile Device Management (MDM) **Experience:** 10 + Read more
Sonographer - *Apple* Hill Imaging Center -...
Sonographer - Apple Hill Imaging Center - Evenings Location: York Hospital, York, PA Schedule: Full Time Full Time (80 hrs/pay period) Evenings General Summary Read more
*Apple* Systems Administrator - JAMF - Activ...
…**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.