Shared Libraries in CPX
Volume Number: 12
Issue Number: 8
Column Tag: Programming Workshop
Using Shared Libraries in CPX
Can you really use the Code Fragment Manager and not go crazy?
By John Shackelford
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
Introduction
The Power Mac and upgrades to System 7 harbor many exciting new technologies
waiting for application developers to explore. One new technology allows executable
code to be shared at run-time. This means you can share code libraries across
applications regardless of which development environment you use - or in other words
you can finally start using all that code those C++ developers are writing down the hall
from you! This technology is provided by a new manager called the Code Fragment
Manager (CFM). The CFM is responsible for loading fragments, blocks of executable
PowerPC code and data, into memory, and preparing them for execution. Currently the
CFM is supported only on Power Macs. However, very soon the CFM will be supported
on 68K Macs.
This article describes and demonstrates with some example code one approach to
accessing shared libraries from Prograph CPX. It shows a way to wrap a C/C++
library, defining an XPrim that provides the interface to shared libraries and
describing in detail a set of CPX classes which encapsulate the use of shared libraries.
You’ll receive many benefits from using shared libraries in your applications,
including reduced development time (because non-Prograph code no longer has to be
ported to the Prograph language) and increased application speed (because of the native
Power Mac code). The code described in this article gives you the basic tools for
accessing shared libraries, listing export symbols, connecting to shared libraries, and
executing functions. The code is shareware, and can be found at Tangent Systems’ Web
page.
Figure 1. The main window for the demo app
Shared Library Demo Application
For this article I have created a simple demo application and two shared libraries. The
demo application will access the shared libraries. The libraries each contain a
different implementation of the same set of functions. One library (OOSharedLib)
implements a set of functions using C++ code, while the other library (ExampleCLib)
uses all C code.
When the application launches and opens its main window (Figure 1), it also
“opens” or “connects to” the two shared libraries. The exported symbols or functions
contained in each library are then available for the application to use. The functions
or symbols that a library exports are listed in the main window. The functions in each
library have been designed to operate on an array of data, and can compute the
maximum, minimum, average, variance, or sum of the data.
You can select the desired library by choosing its name in the pop-up menu. The
scroll list on the left side of the window lists the exported symbols of the selected
shared library. When a symbol is selected in this scrolling list, the Do Function
button becomes active. When the Do Function button is pushed, the selected function
in the selected library is executed. The results are then listed in the right-hand scroll
list.
The pop-up menu in the window lists the two shared libraries the application
will work with. These libraries are loaded when the main window opens by a call to
the window’s method /loadLibraries (Figure 2). A Shared Library instance is
created for each shared library and stored in an attribute of the main window for later
use.
Figure 2. Test Window has a method which loads
a list of shared libraries
Exported symbols are the items which can be referenced by other code fragments.
You can think of exported symbols as the public functions the library supports.
Internally there may be a lot of functions that are hidden from the outside world. This
provides some measure of control over how the library is used - which can be a nice
feature for developers and users. As a developer, I may not always want every function
in the library to be exposed, for fear they might not be properly used; and as a user, I
may not want to know all the gory details of someone else’s library. The typical Power
Mac development environment has a procedure you must follow to define the export
symbols. In CodeWarrior, for instance, there is a file (*.exp) you can edit prior to
building the shared library, that controls which symbols will be exported (more on
this later on).
Now let’s try one function with the demo; then we will dive into more Prograph
code. With the application still running, select a function in the function list and click
Do Function (or simply double-click a function in the function list).
The demo application on the CPX side of things generates a list of 50 numbers. It
then sends this list (embedded in a data structure) as an argument to the chosen
function in the shared library. The shared library function then calculates the result
and sends it back to the application (Figure 3). For the case where we use
OOSharedLib and its get_average function, I did some timing analysis and found that a
pure Prograph-coded equivalent using CPX built-in list primitives can be slower (I
compared 68K compiled CPX to using a PPC-native shared library). Using 8000
values on a Power Mac 7100/80 (System 7.5), I got these results:
Interpreted CPX 200 Ticks
Compiled CPX 20 Ticks
Using native shared library < 1 Tick
(By the way, in looking at my Prograph code, don’t be put off by the
idiosyncracies of my shorthand comments to myself, where I’m reminding myself what
data type is being input or output. “” means Shared Library,
an instance of the Shared Library class; at the time I was writing that comment I
didn’t know how to type the '' character! Use of parentheses generally indicates a
list; so, for instance, “():name” means “a list of names”.)
Figure 3. The method /doFunction handles the execution of the selected library
function
The local setup data_cache builds up a vector of data in a data structure to be
sent off to the shared library. Figure 4 shows the fields of this structure. The