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

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

Nurse Anesthetist - *Apple* Hill Surgery Ce...
Nurse Anesthetist - Apple Hill Surgery Center Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
Housekeeper, *Apple* Valley Village - Cassi...
Apple Valley Village Health Care Center, a senior care campus, is hiring a Part-Time Housekeeper to join our team! We will train you for this position! In this role, Read more
Sublease Associate Optometrist- *Apple* Val...
Sublease Associate Optometrist- Apple Valley, CA- Target Optical Date: Apr 20, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92307 **Requisition Read more
*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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.