Nitrogen: A C++ Wrapper for Carbon


Foreword by Lisa Lippincott

Nitrogen is a C++ interface to the Macintosh operating system, based on Apple's Carbon interface. It also serves as the exemplar of an economical approach to adapting C libraries to C++. This approach is described in detail in the founding document for Nitrogen, The Nitrogen Manifesto.

In brief, I feel that the common approach of designing C++ classes to express the object-oriented concepts underlying a C library is an approach doomed by its excessive ambition. A great deal of effort must go into designing, documenting, and understanding such a library. In effect, such a library reexamines the problem space of the original C library, and produces a new design suited to C++. Such redesign is expensive, particularly when one considers the cost of documenting the design and the cost to users of learning the new design. And if the C library continues to evolve, the design may need to be rethought.

In contrast, the Nitrogen approach focuses design effort on the difference between the C and C++ libraries. A set of rules expressing the difference are developed, and the C++ library parallels C library, separated uniformly by those rules. This rigid uniformity reduces the need for documentation. For the most part, the C++ library can rely on the documentation for the C library, coupled with meta-documentation: The rules relating the C library to the C++ library are documented, so a programmer who knows the C library can deduce the form of the C++ library.

For example, a fundamental rule in Nitrogen is name reuse: each Carbon function name in the global namespace is reused in the Nitrogen namespace for the same purpose. In Carbon, one may create a menu with CreateNewMenu; therefore one may also create a menu with Nitrogen::CreateNewMenu. And both the signature and the semantics of the Nitrogen function can be inferred from the signature and semantics of the Carbon function:

    OSStatus
    CreateNewMenu( MenuID          menuID,
                   MenuAttributes  menuAttributes,
                   MenuRef*        outMenuRef );
Sets *outMenuRef to a newly created menu with the given ID and attributes. The usual value for the attributes is zero. The caller is responsible for disposing of the menu with DisposeMenu. On failure, returns a nonzero error code. Specifically documented error codes include paramErr and memFullErr.
    namespace n = nucleus;
    namespace N = Nitrogen;
    
    n::owned< MenuRef >
    N::CreateNewMenu( N::MenuID          menuID,
                      N::MenuAttributes  menuAttributes = N::MenuAttributes() );
Returns a newly created menu with the given ID and attributes. The result type n::owned< MenuRef > is a std::auto_ptr-like type associated with DisposeMenu. On failure, exits with an exception. Noteworthy exceptions include N::OSStatus and its subclasses paramErr and memFullErr.

This function illustrates several of the most common Nitrogen rules:

[The original document predates the split into separate Nitrogen and Nucleus libraries. This version is updated to match current usage with the Metamage codebase. -- jjuran]