Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: PowerPC System Software /
Chapter 3 - Code Fragment Manager


Using the Code Fragment Manager

The Code Fragment Manager provides routines that you can use to explicitly load code fragments and to get information about symbols exported by a particular fragment. This section illustrates how to use those routines.

IMPORTANT
In general, the Code Fragment Manager automatically loads all import libraries required by your application at the time your application is launched. You need to use the routines described in this section only if your application supports dynamically loaded application tools, filters, or other code modules.
This section also describes how to create a code fragment resource. Every application and import library must have a code fragment resource to describe basic information about the application or import library.

Loading Code Fragments

You can use the Code Fragment Manager to load fragments from the containers in which they are stored. You need to do this only for code fragments that are dynamically added to your application's context during execution. This might happen, for instance, if your application supports dynamically loadable filters or tools.

The executable code you want to bind to your application context can be stored in any kind of container. If the container is an import library (a file of type 'shlb'), you can use the Code Fragment Manager's GetSharedLibrary function. If the container is a disk file, you call the GetDiskFragment function. If the container is a resource, you need to load the resource into memory (using normal Resource Manager routines)
and then call the GetMemFragment function. See "Loading Fragments" beginning on page 3-19 for complete details on each of these functions.

Listing 3-2 and Listing 3-3 illustrate how to load application-specific tools into
memory using the Code Fragment Manager. Listing 3-2 shows how to load a resource-based fragment.

Listing 3-2 Loading a resource-based fragment

Handle         myHandle;
OSErr          myErr;
ConnectionID   myConnID;
Ptr            myMainAddr;
Str255         myErrName;

myHandle = GetResource('tool', 128);
HLock(myHandle);
myErr = GetMemFragment(*myHandle, GetHandleSize(myHandle), 
               myToolName, kLoadNewCopy, &myConnID, 
               (Ptr*)&myMainAddr, myErrName);
if (myErr) {
   AlertUser(myErr);
   goto noLoad;
}
As you can see, Listing 3-2 loads the resource into memory by calling the Resource Manager function GetResource and locks it by calling the Memory Manager procedure HLock. Then it calls GetMemFragment to prepare the fragment. The first parameter passed to GetMemFragment specifies the address in memory of the fragment. Because GetResource returns a handle to the resource data, Listing 3-2 dereferences the handle to obtain a pointer to the resource data. To avoid dangling pointers, you need to lock the block of memory before calling GetMemFragment. The constant kLoadNewCopy passed as the fourth parameter requests that the Code Fragment Manager allocate a new copy of the fragment's global data section.

Listing 3-3 shows how to load a disk-based fragment.

Listing 3-3 Loading a disk-based fragment

myErr = GetDiskFragment(&myFSSpec, 0, kWholeFork, myToolName, 
               kLoadNewCopy, &myConnID, (Ptr*)&myMainAddr, 
               myErrName);
if (myErr) {
   AlertUser(myErr);
   goto noLoad;
}
All import libraries and other fragments that are loaded on behalf of your application (either as part of its normal startup or programmatically by your application) are unloaded by the Process Manager at application termination; therefore, a library can be loaded and does not have to be unloaded by the application before it terminates.

Creating a Code Fragment Resource

You need to create a code fragment resource (a resource of type 'cfrg') for each native application or import library you create. This resource identifies the instruction set architecture, location, size, and logical name of the application or import library, as well as version information for import libraries.

In PowerPC or fat applications, the code fragment resource is read by the Process Manager at application launch time. The Process Manager needs to know whether the application contains PowerPC code and, if so, where that code is located. If the Process Manager cannot find a 'cfrg' resource in the application's resource fork, it assumes that the application is a 680x0 application, where the executable code is contained within 'CODE' resources in the application's resource fork.

IMPORTANT
A code fragment resource must have resource ID 0.
For an application, the code fragment resource typically indicates that the application's executable code fragment begins at offset 0 within the application's data fork and extends for the entire length of the data fork. Listing 3-4 shows the Rez input for a typical application's code fragment resource.

Listing 3-4 The Rez input for a typical application's 'cfrg' resource

#include "CodeFragmentTypes.r"
resource 'cfrg' (0) {
   {
      kPowerPC,               /*instruction set architecture*/
      kFullLib,               /*no update level for apps*/
      kNoVersionNum,          /*no current version number*/
      kNoVersionNum,          /*no oldest def'n version number*/
      kDefaultStackSize,      /*use default stack size*/
      kNoAppSubFolder,        /*no library directory*/
      kIsApp,                 /*fragment is an application*/
      kOnDiskFlat,            /*fragment is on disk*/
      kZeroOffset,            /*fragment starts at fork start*/
      kWholeFork,             /*fragment occupies entire fork*/
      "SurfWriter"            /*name of the application*/
   }
};
Note
See "The Code Fragment Resource" on page 3-28 for complete information about the structure of a code fragment resource.
For import libraries, the code fragment resource is read by the Code Fragment Manager as part of the process of searching for symbols imported by some fragment that is currently being loaded and prepared for execution. (See the section "Import Library Searching" on page 3-5 for details on how the Code Fragment Manager searches for import libraries.) The information in the 'cfrg' resource is also used to ensure that the Code Fragment Manager finds an implementation version of an import library that is compatible with the definition version used to link the fragment being loaded and prepared for execution. Listing 3-5 shows the Rez input for a typical code fragment resource for an import library.

Listing 3-5 The Rez input for a typical import library's 'cfrg' resource

#define kOldDefVers     0x01008000     /*version 1.0*/
#define kCurrVers       0x02008000     /*version 2.0*/

#include "CodeFragmentTypes.r"
resource 'cfrg' (0) {
   {
      kPowerPC,               /*instruction set architecture*/
      kFullLib,               /*base library*/
      kCurrVers,              /*current version number*/
      kOldDefVers,            /*oldest definition version number*/
      kDefaultStackSize,      /*ignored for import library*/
      kNoAppSubFolder,        /*ignored for import library*/
      kIsLib,                 /*fragment is a library*/
      kOnDiskFlat,            /*fragment is on disk*/
      kZeroOffset,            /*fragment starts at fork start*/
      kWholeFork,             /*fragment occupies entire fork*/
      "SurfTools"             /*name of the library*/
   }
};
An import library's code fragment resource also specifies the logical name of the import library. This is the name used by the Code Fragment Manager to resolve imports in some other fragment. The logical name can be different from the name of the file containing the import library.

Note that code fragment resources are required only for fragments that are either applications or import libraries. If you need similar version-checking or name-binding capabilities for fragments that are application extensions, you will need to provide your own code to do this.

Getting Information About Exported Symbols

In cases in which you load a fragment programmatically (that is, by calling Code Fragment Manager routines), you can get information about the symbols exported
by that fragment by calling the CountSymbols and GetIndSymbol functions.
The CountSymbols function returns the total number of symbols exported by a fragment. CountSymbols takes as one of its parameters a connection ID; accordingly, you must already have established a connection to a fragment before you can determine how many symbols it exports.

Given an index ranging from 1 to the total number of symbols in a fragment, the GetIndSymbol function returns the name, address, and class of a symbol in that fragment. You can use CountSymbols in combination with GetIndSymbol to get information about all the symbols in a fragment. For example, the code in Listing 3-6 prints the names of all the symbols in a particular fragment.

Listing 3-6 Finding symbol names

void MyGetSymbolNames (ConnectionID myConnID);
{
   long           myIndex;
   long           myCount;       /*number of exported symbols in fragment*/
   OSErr          myErr;
   Str255         myName;        /*symbol name*/
   Ptr            myAddr;        /*symbol address*/
   SymClass       myClass;       /*symbol class*/

   myErr = CountSymbols(myConnID, &myCount);
   if (!myErr)
      for (myIndex = 1; myIndex <= myCount; myIndex++)
         {
            myErr = GetIndSymbol(myConnID, myIndex, myName, 
                                    &myAddr, &myClass);
            if (!myErr)
               printf("%P", myName);
         }
}
If you already know the name of a particular symbol whose address and class you want to determine, you can use the FindSymbol function. See page 3-24 for details on calling FindSymbol.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
3 JUL 1996