Important: The information in this document is obsolete and should not be used for new development.
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.
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.
- 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.
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'sGetSharedLibrary
function. If the container is a disk file, you call theGetDiskFragment
function. If the container is a resource, you need to load the resource into memory (using normal Resource Manager routines)
and then call theGetMemFragment
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 functionGetResource
and locks it by calling the Memory Manager procedureHLock
. Then it callsGetMemFragment
to prepare the fragment. The first parameter passed toGetMemFragment
specifies the address in memory of the fragment. BecauseGetResource
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 callingGetMemFragment
. The constantkLoadNewCopy
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.
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.
- IMPORTANT
- A code fragment resource must have resource ID 0.
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*/ } };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
- Note
- See "The Code Fragment Resource" on page 3-28 for complete information about the structure of a code fragment resource.
'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 theCountSymbols
andGetIndSymbol
functions.
TheCountSymbols
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 useCountSymbols
in combination withGetIndSymbol
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 theFindSymbol
function. See page 3-24 for details on callingFindSymbol
.