TweetFollow Us on Twitter

Carbonization 101 Volume Number: 16 (2000)
Issue Number: 12
Column Tag: Carbon Development

Carbonization 101

By Éric Simenel

Easier than you might think and so rewarding

The Benefits of Carbon

A beta version of Mac OS X has just been released to the public and a final version should be released in early 2001.


Figure 1. Mac OS X applications.

Four different kinds of applications, shown in Figure 1, can run on Mac OS X:

  1. unmodified Mac OS applications currently running on Mac OS 9 or earlier, will run in the Classic environment. The User Experience will be the same as the one provided with Mac OS 9, and if one of the applications running in that environment encounters a serious problem, it may bring down the whole environment and thus any other application running in that environment.
  2. Java applications, developed using only the JDK and companion libraries.
  3. Cocoa applications, developed in either java or Objective-C (possibly mixed with C/C++), and using the Cocoa frameworks.
  4. and, last but not least, Carbon applications which are slightly modified Mac OS applications.

Each of the last three kinds of application, Java, Cocoa, and Carbon, all run as separate processes in their own protected memory area. If any of those applications encounters a serious problem, it won't affect the others.

The benefits, then, of Carbonizing an application should be apparent: for the cost of a few hours or days of work, you get a much more robust and impervious application that your users can run without problems. Another advantage is that a carbonized application gives you the Aqua theme user interface on Mac OS X.

Carbon being present, through the installation of CarbonLib, on Mac OS 9, 8.6, and 8.1, a Carbonized application, as a single binary, can run on all Mac OS from 8.1 to X.

The Scope of Carbon

Most applications and some plug-ins can be carbonized successfully. Extensions (INITs), Control Panels (cdev), and drivers of any sort cannot be carbonized since they don't run on Mac OS X and the main goal of Carbon is to provide an easy transition for developers from Mac OS 8 and 9 to Mac OS X.

Which version of Carbon should be used?

The version of Carbon that you choose depends on your goals and the configurations that you are targeting. If you want the maximum Mac OS coverage, use only Carbon 1.0.4 APIs which are supported from Mac OS 8.1 to Mac OS X. CarbonLib 1.0.4 gives most of the Toolbox APIs, plus the Control, Window, and Menu Properties, Navigation Services, the Core Foundation APIs, and Carbon Printing 1.0. If, when carbonizing, you find that you are missing a desired functionality, check if it is provided in the Carbon 1.1 APIs which give you access to Appearance 1.1, Carbon Events (which offer an alternative to patching the Toolbox), the new DataBrowser control, ATSUI, URL Access, Keychain, FontSync, XML, HTMLRenderingLib, and others. Choosing the Carbon 1.1 APIs will restrict your target configurations to Mac OS 8.6 and above.

Note: Carbon on Mac OS X, and its companion CarbonLib for Mac OS 8 and 9, are not a closed API but an ongoing development. Future Apple technologies might be delivered only through the Carbon APIs.

The Carbon Porting Process

Let's examine the nuts-and-bolts to see how porting to Carnon can be done. The goal of this article is not to be a rewrite of the "Carbon Porting" document which can be found in the Carbon SDK (see the bibliography at the end of the article for useful URLs), but rather a step-by-step guide based on DTS Engineers' experiences during various Carbon Porting lab events with 3rd-party developers at Apple.

This is not just a bunch of recipes, although you may find them very useful, but rather a methodology to apply when you encounter a problem not yet covered in any documentation.

Estimating how much work will be required

Of course, the amount of work depends on the size of the source code and the number of unsupported APIs in your source code. Experience in the Carbon Porting labs tells us that most developers can successfully carbonize 80% or more of their applications in the 3 to 5 days of that event.

CarbonDater is a tool which may help you quickly determine the amount of work to be done. An example of a Carbon Compatibility Report is shown in Figure 2.


Figure 2. The Carbon Compatibility Report.

The Carbon Compatibility Report also provides a fairly detailed analysis and some suggestions as to how to replace unsupported APIs (Figure 3) and the kinds of modifications you will have to make in order to be Carbon-compliant (Figure 4).


Figure 3. Unsupported API.


Figure 4. Modified API.

Another way to estimate the necessary amount of time is to plunge right into the Carbonization process; the first compilation will give you an idea of the extent of the work to be done.

First things first

As the "Carbon Porting Guide" suggests, it's best to update your project to the latest Universal Headers first. If you're interested in Carbon 1.0, then use the Universal Headers 3.3.2, but if you're interested in Carbon 1.1, then use the Universal Headers 3.4. If you are developing with CodeWarrior, be careful to follow the instructions (from your CodeWarrior User's manual) and update any pre-compiled headers if you're using them.

The next step depends on the size of your project and the way you prefer to develop. You can either follow all the steps described in the "Carbon Porting Guide" (which is preferable if your project is large), or follow these instructions (which assume you are using CodeWarrior, any version after and including Pro 2):

  • first, clone your existing PowerPC target,
  • second, add the preprocessor command #define TARGET_API_MAC_CARBON 1 to the beginning of your project's prefix file (if you already have a prefix file, then duplicate it, add the preprocessor command in one of them and use this one for your Carbon target),
  • and third, remove all Apple stub libraries such as InterfaceLib and any others that you might have needed in your project such as AppearanceLib, WindowsLib, etc., and add the CarbonLib stub instead. You can keep non-Apple libraries such as "MSL RuntimePPC.Lib", "MSL C.PPC.Lib", etc.

If you are using any other libraries, then you will need to determine (the PEF Viewer utility can help you do that) if the code they contain is importing any symbols from InterfaceLib or any of those Apple libraries at runtime. If that's not the case then they should be safe to use as is, but if they are , then those libraries will have to be carbonized as well.

After you're finished with those 3 steps, which shouldn't take you more than a few minutes, then attempt your first build.

You will get many, perhaps thousands, of errors.

Luckily, 80% of them, if not more, are repeats and just illegal access to Toolbox structures which are now opaque or illegal type usage (DialogPtr, WindowPtr, and GrafPtr are now 3 different pointer types and can't be used in place of each other). Addressing those errors is simple but tedious, and it just takes time. There are 2 different ways to fix those errors, one involving the CarbonAccessors.o library, and the other one involving conditional compilation. For instance, the following extract, which should be quite common in your source code:

   WindowPtr theWind;
   ...
   SetPort(theWind);

is going to generate the compiler error:

Error:
cannot convert 'OpaqueWindowPtr *' to 'OpaqueGrafPtr *'

You can either change the source code to

   SetPortWindowPort(theWind);

and add the CarbonAccessors.o library to your non-Carbon targets in your project or change the source code to

#if !TARGET_API_MAC_CARBON
   SetPort(theWind);
#else
   SetPortWindowPort(theWind);
#endif

and you don't have to add the library.

The advantage of the former solution is that the source code is more readable but your non-Carbon application is going to grow by about 60K, whereas the advantage of the latter is that your non-Carbon application stays rigorously the same, but you will have to add a lot of those #if !TARGET_API_MAC_CARBON lines in your source code which can also look like:

#if !TARGET_API_MAC_CARBON
   yLocation = theWind->portRect.bottom-10;
#else
   Rect thePortRect;
   GetWindowPortBounds(theWind, &thePortRect);
   yLocation = thePortRect.bottom-10;
#endif

It's your choice.

Finding out Carbon information

The best way to find out is to apply the following methodology: in the previous example, you tried to access the portRect field of the WindowPtr theWind. This is doubly illegal because the variable theWind is a WindowPtr and not a GrafPtr, and also because both WindowPtr and GrafPtr are opaque structures anyway. So the obvious solution is to look at the GrafPort structure definition in QuickDraw.h and there you will see that it changed to:

struct GrafPort {
   short device;   /* not available in Carbon*/
   BitMap portBits;   /* in Carbon use GetPortBitMapForCopyBits 
      or IsPortColor*/
   Rect portRect;   /* in Carbon use Get/SetPortBounds*/
   ...
   };

and if you look for GetPortBounds you will find it at the end of QuickDraw.h in the /* Getters */ section:

EXTERN_API( Rect *)
   GetPortBounds(CGrafPtr port, Rect * rect);

So now you know how to get the portRect out of a GrafPtr (or a CGrafPtr, both are equivalent in Carbon since the structures they point to are opaque), but what you have is a WindowPtr. Again, since the port of the window is in fact a field in the WindowRecord structure you just open MacWindows.h and you look at the WindowRecord (or CWindowRecord) structure definition and there you will see that it changed to:

struct WindowRecord {
   GrafPort port;   /* in Carbon use GetWindowPort*/
   short windowKind;   /* in Carbon use Get/SetWindowKind*/
   ...
   };

And if you look for GetWindowPort you will find it at the end of MacWindows.h in the /* Getters */ section (do you see a pattern here?):

EXTERN_API( CGrafPtr ) GetWindowPort(WindowRef window);

Don't worry about the WindowRef type which is the same as WindowPtr (defined in QuickDraw.h for practical reasons).

So you could write:

#if !TARGET_API_MAC_CARBON
   yLocation = theWind->portRect.bottom-10;
#else
   Rect thePortRect;
   CGrafPtr theWindowPort;
   theWindowPort = GetWindowPort(theWind);
   GetPortBounds(theWindowPort, &thePortRect);
   yLocation = thePortRect.bottom-10;
#endif

but, in order to simplify and reduce the coding, Apple also provided a direct GetWindowPortBounds call that you also find at the end of MacWindows.h:

EXTERN_API( Rect *)
   GetWindowPortBounds(WindowRef window, Rect * bounds);

so that's why you can write the shorter code shown in the previous section. Apple provided those shortcuts for the most common usage.

Since the GetWindowPortBounds call (like the others) returns the same Rect* as being passed as the second parameter, you could even write:

#if !TARGET_API_MAC_CARBON
   yLocation = theWind->portRect.bottom-10;
#else
   Rect thePortRect;
   yLocation = 
      GetWindowPortBounds(theWind, &thePortRect)->bottom-10;
#endif

or even, if you keep a global scratch variable Rect gTempRect around which will be used for such operations you could write:

#if !TARGET_API_MAC_CARBON
   yLocation = theWind->portRect.bottom-10;
#else
   yLocation = 
      GetWindowPortBounds(theWind, &gTempRect)->bottom-10;
#endif

Again, it's your choice.

Sometimes, the comments provided in the Header files for Carbonization advice are not on the same line as the information you're looking for, but usually they're not too far away. In the following case for example:

   GrafPtr currentPort;
   GetPort(&currentPort);
   EraseRect(&currentPort->portRect);
   InvalRect(&currentPort->portRect);

will bring you:

Error : undefined identifier 'portRect'
SampleWindows.cp line 336 EraseRect(&currentPort->portRect);
Error : undefined identifier 'InvalRect'
SampleWindows.cp line 337 InvalRect(&currentPort->portRect);

The incorrect usage of portRect will be fixed by a simple call to GetPortBounds as previously but what about InvalRect? A search for InvalRect (in MacWindows.h) will make apparent that we now have:

#if CALL_NOT_IN_CARBON
EXTERN_API( void ) InvalRect(const Rect * badRect) ONEWORDINLINE(0xA928);
...
#endif   /* CALL_NOT_IN_CARBON */

so we have to look around and we will see that for this call as well as for InvalRgn, ValidRect, and ValidRgn, we have a comment above which says:

/*
   These aren't present in Carbon. Please use the InvalWindowRect, etc. routines
   below instead.
*/

So we will diligently replace the illegal code with:

   Rect thePortRect;
   GetPortBounds(currentPort, &thePortRect);
   EraseRect(&thePortRect);
   InvalWindowRect(GetWindowFromPort(currentPort), 
                        &thePortRect);

You will note that we also used the utility function GetWindowFromPort which you can find in MacWindows.h as well.

What happened to my qd?

The global variable qd has been removed so if you had been using some code like:

   DragWindow(theWind, theEvent->where, 
                  &qd.screenBits.bounds);

then, after looking for screenBits in QuickDraw.h and finding the relevant comment, you will have to write:

   Rect bounds;
#if !TARGET_API_MAC_CARBON
   bounds = qd.screenBits.bounds;
#else
   BitMap bmap;
   GetQDGlobalsScreenBits(&bmap);
   bounds = bmap.bounds;
#endif
   DragWindow(theWind, theEvent->where, &bounds);

What happened to my InitGraf and other Toolbox Managers Initialization calls?

Most of them are now just unneeded in Carbon so you can just conditional-compile out InitGraf, InitFonts, InitWindows, InitMenus, TEInit, and InitDialogs. You must still use InitCursor. Typical initialization memory schemes such as the manipulation of the heap limit (SetApplLimit and GetApplLimit) as well as MaxApplZone are also prohibited in Carbon.

For obsolescence reasons, the support for Desk Accessories is no longer required in applications so SystemClick and OpenDeskAcc have also been removed from Carbon.

So is it just searching, finding, and replacing?

Although at least 80% or more of the errors you will get at the first compilation will indeed be no more problematic than that, still it's not going to be that simple for the remaining 20% or less.

First you have to deal with the modified calls such as NewCWindow (and NewWindow, NewDialog, and NewColorDialog as well for the same reason) which does not accept a storage parameter anymore. Unfortunately the compiler will not alert you that such calls are going to fail although you will get a null return value from the call so if you have a good error-checking code you will easily detect the problem at runtime rather than crashing. The main reason developers were passing a storage as first parameter is that they wished to extend the Toolbox structure with their own fields, and to lessen heap fragmentation. Since those structures are opaque, this is no longer possible. So you will have to modify such declarations:

Note: All error-checking code has been removed from the sample code extracts present in this article so that the modifications you have to apply in order to Carbonize are more evident. Real code would need error-checking...

typedef struct
   {
   WindowRecord theWind;
   OSType theSignature;
   GWorldPtr theGWorld;
   ...
   } MyWind, *MyWindPtr;

in

typedef struct
   {
#if ! TARGET_API_MAC_CARBON
   WindowRecord theWind;
#else
   WindowPtr theWind;
#endif
   OSType theSignature;
   GWorldPtr theGWorld;
   ...
   } MyWind, *MyWindPtr;

and change from:

   wind = (MyWindPtr)NewPtr(sizeof(MyWind));
   if (wind != 0L)
      {
      wind->theSignature = kSig;
      NewCWindow(wind, &rBounds, fName, 1, 
                     noGrowDocProc, (WindowPtr)-1L, 1, 0L);
      ...
      }

to:

   wind = (MyWindPtr)NewPtr(sizeof(MyWind));
   if (wind != 0L)
      {
      wind->theSignature = kSig;
#if ! TARGET_API_MAC_CARBON
      NewCWindow(wind, &rBounds, fName, 1, 
                     noGrowDocProc, (WindowPtr)-1L, 1, 0L);
#else
      wind->theWind = NewCWindow(NULL, &rBounds, fName, 1, 
                     noGrowDocProc, (WindowPtr)-1L, 1, (long)wind);
#endif
      ...
      }

and you can still extract your MyWind structure location from the refCon value of your WindowPtr. If you were already using the refCon field to store some other information, then you can keep that information in the structure MyWind instead. Another solution is to use the new functions SetWindowProperty and GetWindowProperty which enable to attach tagged information to any window.

Another likely modification you will have to make is the control list walk-through. Previously you could just start from the controlList field of the structure WindowRecord, but of course this field is no longer accessible in the opaque structure and there are no accessor function to retrieve it. In order to get the first control of the control list of a window, you will have to modify your code like this:

   // window creation with NewWindow, or NewCWindow, 
   // or CreateNewWindow (preferred...), or...

#if TARGET_API_MAC_CARBON
      ControlRef theRootControl;
      if (theWindow != NULL)
         CreateRootControl(theWindow, &theRootControl);
#endif

and later:

#if !TARGET_API_MAC_CARBON
   ControlHandle theControl = (ControlHandle)
      (((WindowPeek)theWindow)->controlList);
   while (theControl != NULL)
#else
   UInt16 numChildren, index;
   ControlRef rootControl, theControl;
   GetRootControl(theWindow, &rootControl);
   CountSubControls(rootControl, &numChildren);
   for (index = numChildren; index >= 1; index—)
#endif
      {
#if TARGET_API_MAC_CARBON
      GetIndexedSubControl(rootControl, index, &theControl);
#endif
      // do something with theControl,
      // you can even dispose it since we're doing a reverse loop
#if !TARGET_API_MAC_CARBON
#if DISPOSINGCONTROL
      theControl = (ControlHandle)
         (((WindowPeek)theWindow)->controlList);
#else
      theControl = (*theControl)->nextControl;
#endif
#endif
      }

If you didn't add support for the Navigation Services, to replace the use of the Standard File Package, now is the time since Carbon does not support the Standard File Package.

Another whole section of the traditional Macintosh Toolbox, the Scrap Manager, has also been revised in Carbon. Most applications use the Scrap Manager routines in a fairly straightforward way and the amount of modifications you may have to apply may not be much more complicated than the following.

For copying:

#if !TARGET_API_MAC_CARBON
   ZeroScrap();
#else
   ScrapRef scrapRef;
   ClearCurrentScrap();
   status = GetCurrentScrap(&scrapRef);
#endif

#if !TARGET_API_MAC_CARBON
   PutScrap(byteLength, 'utxt', *hUnicodeText);
#else
   status = PutScrapFlavor(scrapRef, 'utxt',
      kScrapFlavorMaskNone, byteLength, *hUnicodeText);
#endif

And for pasting:

#if !TARGET_API_MAC_CARBON
   LoadScrap();
#else
   ScrapRef scrapRef;
   status = GetCurrentScrap(&scrapRef);
#endif

#if !TARGET_API_MAC_CARBON
   long offset, byteLength = GetScrap(NULL, 'utxt', &offset);
#else
   long byteLength;
   status = GetScrapFlavorSize(scrapRef, 'utxt', &byteLength);
#endif

   if (byteLength <= 0) return;

#if !TARGET_API_MAC_CARBON
   Handle hUnicodeText = NewHandle(0);
   GetScrap(hUnicodeText, 'utxt', &offset);
#endif
   
   // let's grab the text from the scrap
   UniCharCount uTextLength = byteLength / sizeof(UniChar);
   UniCharArrayPtr theUnicodeText =
      (UniCharArrayPtr)NewPtr(byteLength);

#if !TARGET_API_MAC_CARBON
   HLock(hUnicodeText);
   BlockMoveData(*hUnicodeText, (Ptr)theUnicodeText,
      byteLength);
#else
   status = GetScrapFlavorData(scrapRef, 'utxt', &byteLength,
      theUnicodeText);
#endif

Almost there since we should just comment out all the printing code for now. The Printing Manager has been revised also in Carbon and in such ways that it could be the only subject of another MacTech article by itself, so we're not going to deal with that in this article.

Patience and labor will get you to a point where you no longer get any compilation errors.

But now you'll see link errors.

Maybe some will be due to Toolbox calls present in the headers but missing in the CarbonLib shared library (this is still a work in progress), but most of the errors will come from the use of MSL (MetroWerks Standard Library). You will either have to use the updated for Carbon version of MSL from MetroWerks (which is part of CodeWarrior Pro 6 which also contains a fully carbonized version of PowerPlant) or get rid entirely of any dependencies on this package.

Again, patience and labor will get you to a point where you no longer get any link errors.

And you should thus be able to test your application on Mac OS 9 (recommended for the first runs), and it should run fine although you may have to increase the memory partition (resource 'SIZE ' id -1).

Depending on the version of CarbonLib you've been developing against, you can also test the running of your application on 8.6 and 8.1.

But the real test will of course be the running on Mac OS X!

Running on Mac OS X

If you just launch your recently carbonized application on Mac OS X, you may not see a single difference in either behavior or even appearance with your application running on Mac OS 9. The most probable cause is that you're in fact running your carbonized application in the Classic environment! If you don't see your application interface using the Aqua theme user interface, then you are running in the Classic environment. In order for your application to be run as a Carbon Application, and thus in its own memory-protected space and with the Aqua theme user interface, you have to let Mac OS X know about the fact that you did your job and carbonized this application. You do that by adding both a 'carb' resource with id 0, the content does not matter, and usually you'll just set a single byte as 0, and adding a 'plst' resource, also with id 0, which contains the XML representation of the application's property list. If those 2 resources are present in your application then Mac OS X will launch your application as a Carbon process with all the advantages that come with it.

Note: If you have been following the suggested steps described above, you should have at least 3 different targets for your project: debug-Classic, non-debug-Classic, non-debug-Carbon. Your may have more... Since all those targets can run on Mac OS X, either being launched in the Classic environment, or launched as a Carbon process, it might be useful to be able to identify at runtime, with certainty, which target you're currently running. You could use the following routines (or adapt them to your needs) to achieve identification:

Boolean IsThisX()
   {
   long response;
   OSErr err = Gestalt(gestaltSystemVersion, &response);
   return ((err == noErr) && (response >= 0x00000A00));
   }

Boolean IsThisAqua()
   {
   long response;
   OSErr err = Gestalt(gestaltMenuMgrAttr, &response);
   return
      (
         (err == noErr) &&
         ((response & gestaltMenuMgrAquaLayoutMask) != 0)
      );
   }

void DoAboutBox()
   {
   Str255 theStr, theStr2, theStr3;
#if __option (sym)
   sprintf((char *)theStr2, "Debug Version");
#else
   sprintf((char *)theStr2, "Final Version");
#endif
#if TARGET_API_MAC_CARBON
   if (IsThisAqua())
      sprintf((char *)theStr3, "Carbon Aqua");
   else
      sprintf((char *)theStr3, "Carbon Platinum");
#else
   sprintf((char *)theStr3, "Classic");
#endif
   sprintf((char *)&theStr[1], "%s, %s, %s, %s",
      (char *)theStr2, (char *)theStr3, __DATE__, __TIME__);
   theStr[0] = strlen((char *)&theStr[1]);
   ParamText(theStr, "\p", "\p", "\p"); Alert(128, 0L);
   }

When running on Mac OS X, you will notice that some system menus have changed and some menu items have moved. One important change is that the Quit menu item is now in the Application menu (which replaces the Apple menu of Mac OS 9 and previous). You are no longer supposed to have a Quit menu item in your File menu. That also means, by the way, that you need to have a QuitAppleEventHandler routine since this is the way that Mac OS X will inform your application that the user wants to quit it. You are not supposed to add the "desk accessories" (which have not been true desk accessories for a very long time anyway) in the Apple menu either.

So your menu initialization and installation routine should look like:

   Handle menuBar = GetNewMBar(kMainMenuBar);
   SetMenuBar(menuBar);
   DisposeHandle(menuBar);
#if TARGET_API_MAC_CARBON
   if (IsThisAqua()) // removing the Quit menu item and the separator line
      {
      MenuHandle menu = GetMenuHandle(kFileMenu);
      DeleteMenuItem(menu, kQuitMenuItem);
      DeleteMenuItem(menu, kQuitMenuItem-1);
      }
#else
   AppendResMenu(GetMenuHandle(kAppleMenu), 'DRVR');
#endif
   DrawMenuBar();

And with that fine-tuning achieved, you are pretty much done. You will still have to thoroughly test your application on all Mac OS versions it's supposed to run on, but the job is no more complicated than described here (with the exception of printing which has to be rewritten). You may encounter some mysterious behaviors and the most frequently reported is that the drawing in one of your windows is not happening anymore (typically some kind of animation). The most likely reason for that is that you are drawing in that window outside of its update routine and since windows are double-buffered on Mac OS X, you just keep modifying the bits of the offscreen and nothing happens in the window on the screen. Carbon moves the bits from the offscreen to the window at the end of the update routine and in some other conditions, but not in that case, so you will have to add a bit of tweaking there as well. There are 2 ways to achieve that tweaking, but only one is recommended. QuickDraw.h provides 3 new APIs (QDIsPortBuffered, QDIsPortBufferDirty, and QDFlushPortBuffer) which can be used that way:

   InitTheCircle();
   for (i=startingMonth; i<=endingMonth; i++)
      {
      UnsignedWide startingTime, endingTime;
      Microseconds(&startingTime);
      UpdateTheCircle(i);

      /* on Mac OS X, drawing is double-buffered by default*/

#if TARGET_API_MAC_CARBON
      if (QDIsPortBuffered((CGrafPtr)curPort))
         QDFlushPortBuffer((CGrafPtr)curPort, NULL);
#endif
      do {Microseconds(&endingTime);} while
         (ComputeMicros(&startingTime, &endingTime) <
            kAnimationDelay);
      }
  TermTheCircle();

The other way, which is not recommended, is to add the kWindowNoBufferingAttribute attribute to the WindowAttributes parameter you pass to CreateNewWindow. In that case, the window will not be double-buffered so all drawing will be directed to the window, but you disrupt the normal updating mechanism of the Window Server and, for instance, if you move such a window, you may leave undesirable graphical artifacts on your screen.

Conclusion

If you have more than one application to carbonize, we advise you to start with the most recently developed first since it will be the easiest to carbonize. It should already be using a recent version of the Universal Headers and shouldn't do too many of the various no-no's no longer available in Carbon. Going back in time, carbonizing older and older applications, you will find that the previous experiences will help you to overcome the difficulties arising from carbonizing old code. But the methodology remains the same:

  1. use at least the Universal Headers 3.3.2
  2. for each error, refer to that routine or that structure in the appropriate header and read the Carbonization comments which are sure to be found around.

If for any reason you are at a loss as to what to do or how to do it, then you're more than welcome to join and participate in the Carbon Development mailing list that you can join by sending an email to <requests@sam.apple.com> with "subscribe carbon_development" as the email's message. The Carbon Development mail list is restricted to discussion of Carbon development issues.

If you still can't find satisfaction when participating in the list, you can address your question to <dts@apple.com> but you need to be a member of our programs in order to do that.

References


Éric Simenel simenel.e@apple.com is a software engineer in Apple's DTS (Developer Technical Support) team. He is currently supporting Mac OS 9 and Carbon.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Tokkun Studio unveils alpha trailer for...
We are back on the MMORPG news train, and this time it comes from the sort of international developers Tokkun Studio. They are based in France and Japan, so it counts. Anyway, semantics aside, they have released an alpha trailer for the upcoming... | Read more »
Win a host of exclusive in-game Honor of...
To celebrate its latest Jujutsu Kaisen crossover event, Honor of Kings is offering a bounty of login and achievement rewards kicking off the holiday season early. [Read more] | Read more »
Miraibo GO comes out swinging hard as it...
Having just launched what feels like yesterday, Dreamcube Studio is wasting no time adding events to their open-world survival Miraibo GO. Abyssal Souls arrives relatively in time for the spooky season and brings with it horrifying new partners to... | Read more »
Ditch the heavy binders and high price t...
As fun as the real-world equivalent and the very old Game Boy version are, the Pokemon Trading Card games have historically been received poorly on mobile. It is a very strange and confusing trend, but one that The Pokemon Company is determined to... | Read more »
Peace amongst mobile gamers is now shatt...
Some of the crazy folk tales from gaming have undoubtedly come from the EVE universe. Stories of spying, betrayal, and epic battles have entered history, and now the franchise expands as CCP Games launches EVE Galaxy Conquest, a free-to-play 4x... | Read more »
Lord of Nazarick, the turn-based RPG bas...
Crunchyroll and A PLUS JAPAN have just confirmed that Lord of Nazarick, their turn-based RPG based on the popular OVERLORD anime, is now available for iOS and Android. Starting today at 2PM CET, fans can download the game from Google Play and the... | Read more »
Digital Extremes' recent Devstream...
If you are anything like me you are impatiently waiting for Warframe: 1999 whilst simultaneously cursing the fact Excalibur Prime is permanently Vault locked. To keep us fed during our wait, Digital Extremes hosted a Double Devstream to dish out a... | Read more »
The Frozen Canvas adds a splash of colou...
It is time to grab your gloves and layer up, as Torchlight: Infinite is diving into the frozen tundra in its sixth season. The Frozen Canvas is a colourful new update that brings a stylish flair to the Netherrealm and puts creativity in the... | Read more »
Back When AOL WAS the Internet – The Tou...
In Episode 606 of The TouchArcade Show we kick things off talking about my plans for this weekend, which has resulted in this week’s show being a bit shorter than normal. We also go over some more updates on our Patreon situation, which has been... | Read more »
Creative Assembly's latest mobile p...
The Total War series has been slowly trickling onto mobile, which is a fantastic thing because most, if not all, of them are incredibly great fun. Creative Assembly's latest to get the Feral Interactive treatment into portable form is Total War:... | Read more »

Price Scanner via MacPrices.net

Early Black Friday Deal: Apple’s newly upgrad...
Amazon has Apple 13″ MacBook Airs with M2 CPUs and 16GB of RAM on early Black Friday sale for $200 off MSRP, only $799. Their prices are the lowest currently available for these newly upgraded 13″ M2... Read more
13-inch 8GB M2 MacBook Airs for $749, $250 of...
Best Buy has Apple 13″ MacBook Airs with M2 CPUs and 8GB of RAM in stock and on sale on their online store for $250 off MSRP. Prices start at $749. Their prices are the lowest currently available for... Read more
Amazon is offering an early Black Friday $100...
Amazon is offering early Black Friday discounts on Apple’s new 2024 WiFi iPad minis ranging up to $100 off MSRP, each with free shipping. These are the lowest prices available for new minis anywhere... Read more
Price Drop! Clearance 14-inch M3 MacBook Pros...
Best Buy is offering a $500 discount on clearance 14″ M3 MacBook Pros on their online store this week with prices available starting at only $1099. Prices valid for online orders only, in-store... Read more
Apple AirPods Pro with USB-C on early Black F...
A couple of Apple retailers are offering $70 (28%) discounts on Apple’s AirPods Pro with USB-C (and hearing aid capabilities) this weekend. These are early AirPods Black Friday discounts if you’re... Read more
Price drop! 13-inch M3 MacBook Airs now avail...
With yesterday’s across-the-board MacBook Air upgrade to 16GB of RAM standard, Apple has dropped prices on clearance 13″ 8GB M3 MacBook Airs, Certified Refurbished, to a new low starting at only $829... Read more
Price drop! Apple 15-inch M3 MacBook Airs now...
With yesterday’s release of 15-inch M3 MacBook Airs with 16GB of RAM standard, Apple has dropped prices on clearance Certified Refurbished 15″ 8GB M3 MacBook Airs to a new low starting at only $999.... Read more
Apple has clearance 15-inch M2 MacBook Airs a...
Apple has clearance, Certified Refurbished, 15″ M2 MacBook Airs now available starting at $929 and ranging up to $410 off original MSRP. These are the cheapest 15″ MacBook Airs for sale today at... Read more
Apple drops prices on 13-inch M2 MacBook Airs...
Apple has dropped prices on 13″ M2 MacBook Airs to a new low of only $749 in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, now available for $679 for 8-Core CPU/7-Core GPU/256GB models. Apple’s one-year warranty is included, shipping is free, and each... Read more

Jobs Board

Seasonal Cashier - *Apple* Blossom Mall - J...
Seasonal Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Seasonal Fine Jewelry Commission Associate -...
…Fine Jewelry Commission Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) Read more
Seasonal Operations Associate - *Apple* Blo...
Seasonal Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Read more
Hair Stylist - *Apple* Blossom Mall - JCPen...
Hair Stylist - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom 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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.