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

Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »
Marvel Future Fight celebrates nine year...
Announced alongside an advertising image I can only assume was aimed squarely at myself with the prominent Deadpool and Odin featured on it, Netmarble has revealed their celebrations for the 9th anniversary of Marvel Future Fight. The Countdown... | Read more »
HoYoFair 2024 prepares to showcase over...
To say Genshin Impact took the world by storm when it was released would be an understatement. However, I think the most surprising part of the launch was just how much further it went than gaming. There have been concerts, art shows, massive... | Read more »

Price Scanner via MacPrices.net

Apple Watch Ultra 2 now available at Apple fo...
Apple has, for the first time, begun offering Certified Refurbished Apple Watch Ultra 2 models in their online store for $679, or $120 off MSRP. Each Watch includes Apple’s standard one-year warranty... Read more
AT&T has the iPhone 14 on sale for only $...
AT&T has the 128GB Apple iPhone 14 available for only $5.99 per month for new and existing customers when you activate unlimited service and use AT&T’s 36 month installment plan. The fine... Read more
Amazon is offering a $100 discount on every M...
Amazon is offering a $100 instant discount on each configuration of Apple’s new 13″ M3 MacBook Air, in Midnight, this weekend. These are the lowest prices currently available for new 13″ M3 MacBook... Read more
You can save $300-$480 on a 14-inch M3 Pro/Ma...
Apple has 14″ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more
24-inch M1 iMacs available at Apple starting...
Apple has clearance M1 iMacs available in their Certified Refurbished store starting at $1049 and ranging up to $300 off original MSRP. Each iMac is in like-new condition and comes with Apple’s... Read more
Walmart continues to offer $699 13-inch M1 Ma...
Walmart continues to offer new Apple 13″ M1 MacBook Airs (8GB RAM, 256GB SSD) online for $699, $300 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBook for sale by... Read more
B&H has 13-inch M2 MacBook Airs with 16GB...
B&H Photo has 13″ MacBook Airs with M2 CPUs, 16GB of memory, and 256GB of storage in stock and on sale for $1099, $100 off Apple’s MSRP for this configuration. Free 1-2 day delivery is available... Read more
14-inch M3 MacBook Pro with 16GB of RAM avail...
Apple has the 14″ M3 MacBook Pro with 16GB of RAM and 1TB of storage, Certified Refurbished, available for $300 off MSRP. Each MacBook Pro features a new outer case, shipping is free, and an Apple 1-... Read more
Apple M2 Mac minis on sale for up to $150 off...
Amazon has Apple’s M2-powered Mac minis in stock and on sale for $100-$150 off MSRP, each including free delivery: – Mac mini M2/256GB SSD: $499, save $100 – Mac mini M2/512GB SSD: $699, save $100 –... Read more
Amazon is offering a $200 discount on 14-inch...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $200 off MSRP. Shipping is free. Note that Amazon’s stock tends to come and go: – 14″ M3 MacBook Pro (8GB RAM/512GB SSD): $1399.99, $200... Read more

Jobs Board

*Apple* Systems Administrator - JAMF - Syste...
Title: Apple Systems Administrator - JAMF ALTA is supporting a direct hire opportunity. This position is 100% Onsite for initial 3-6 months and then remote 1-2 Read more
Relationship Banker - *Apple* Valley Financ...
Relationship Banker - Apple Valley Financial Center APPLE VALLEY, Minnesota **Job Description:** At Bank of America, we are guided by a common purpose to help Read more
IN6728 Optometrist- *Apple* Valley, CA- Tar...
Date: Apr 9, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92308 **Requisition ID:** 824398 At Target Optical, we help people see and look great - and Read more
Medical Assistant - Orthopedics *Apple* Hil...
Medical Assistant - Orthopedics Apple Hill York Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now 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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.