Removing the obvious OS9-only documents§
This commit is contained in:
parent
28ecf70db5
commit
d338b6e317
|
@ -1,424 +0,0 @@
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<TITLE>Building MacPython-OS9 from source</TITLE>
|
|
||||||
</HEAD>
|
|
||||||
<BODY>
|
|
||||||
<H1>Building MacPython-OS9 from source</H1>
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
This document explains how to build MacPython-OS9 from source. This is
|
|
||||||
necessary if you want to make modifications to the Python core. Building
|
|
||||||
Python is not something to be undertaken lightly, you need a reasonable
|
|
||||||
working knowledge of the CodeWarrior development environment, a good net
|
|
||||||
connection and probably quite some time too. <p>
|
|
||||||
|
|
||||||
Note that if you only want to build new extension modules you don't need to
|
|
||||||
build Python from source, see the <a href="#extending">note on extending Python</a>.<p>
|
|
||||||
|
|
||||||
The information density in this file is high, so you should probably
|
|
||||||
print it and read it at your leasure. Most things are explained only
|
|
||||||
once (and probably in the wrong place:-). <p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
First a warning: this information may become outdated if a new CodeWarrior is
|
|
||||||
released after MacPython. The
|
|
||||||
<a href="http://www.cwi.nl/~jack/macpython.html">MacPython homepage</a> will
|
|
||||||
hopefully have updated instructions in that case. These instructions are for CW7,
|
|
||||||
it is rumoured you may encounter some problems with newer versions of CodeWarrior.
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
I am interested in feedback on this document, send your
|
|
||||||
comments to the <A
|
|
||||||
HREF="http://www.python.org/sigs/pythonmac-sig/">Mac Python Special
|
|
||||||
Interest Group</A>.
|
|
||||||
|
|
||||||
<H2>What you need.</H2>
|
|
||||||
|
|
||||||
The following things you definitely need:
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
|
|
||||||
<LI> You need a MacPython source distribution, of course. You can
|
|
||||||
obtain one via <A HREF="http://www.cwi.nl/~jack/macpython.html">
|
|
||||||
http://www.cwi.nl/~jack/macpython.html</A> (which has up-to-date links
|
|
||||||
to the other packages needed too) and possibly also from the standard
|
|
||||||
<A HREF="ftp://ftp.python.org/pub/python/mac">python.org ftp
|
|
||||||
site</A>. <BR>
|
|
||||||
|
|
||||||
A better alternative is to check the sources straight out of the CVS
|
|
||||||
repository, see below. Most of the packages mentioned here are also
|
|
||||||
available through CVS. Check the section on <a href="#cvs">CVS
|
|
||||||
repository use</a> below.
|
|
||||||
|
|
||||||
<LI> You need MetroWerks CodeWarrior. The current distribution has
|
|
||||||
been built with CodeWarrior Pro 7.1. Ordering information is
|
|
||||||
available on the <A HREF="http://www.metrowerks.com/">MetroWerks
|
|
||||||
homepage</A>. Building Python with MPW, Think/Symantec C or the OSX
|
|
||||||
developer tools is impossible without major surgery.
|
|
||||||
|
|
||||||
<LI> You need GUSI version 2, the Grand Unified Socket Interface, by
|
|
||||||
Matthias Neeracher. The original GUSI is obtainable from <A
|
|
||||||
HREF="ftp://gusi.sourceforge.net/pub/gusi/">
|
|
||||||
ftp://gusi.sourceforge.net/pub/gusi/</A>. At
|
|
||||||
the moment Python is built with a modified version of GUSI
|
|
||||||
with Carbon adaptations, so it may be better to check the <A
|
|
||||||
HREF="http://www.cwi.nl/~jack/macpython.html">MacPython homepage</A>
|
|
||||||
for a GUSI that is most easily used for building Python.
|
|
||||||
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<A NAME="optional">The MacPython project files are configured to
|
|
||||||
include a plethora of optional modules</A>, and these modules need a
|
|
||||||
number of extra packages. To use the project files as-is you have to
|
|
||||||
download these packages too. Python has all such modules as
|
|
||||||
dynamically loaded modules, so if you don't need a certain package it
|
|
||||||
suffices to just refrain from builing the extension module.
|
|
||||||
Here are the locations for the various things
|
|
||||||
you need:
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
|
|
||||||
<LI> Waste, a TextEdit replacement written by Marco Piovanelli, <A
|
|
||||||
HREF="mailto:piovanel@kagi.com"><piovanel@kagi.com></A>. Python
|
|
||||||
was built using version 2.0, which is included in the CodeWarrior
|
|
||||||
package. You can also obtain it from <A
|
|
||||||
HREF="http://www.merzwaren.com/waste"><http://www.merzwaren.com/waste></A>
|
|
||||||
and various other places.
|
|
||||||
|
|
||||||
<LI> Gdbm library for the Mac. Available from Jack's Mac software page at
|
|
||||||
<A HREF="http://www.cwi.nl/~jack/macsoftware.html">
|
|
||||||
http://www.cwi.nl/~jack/macsoftware.html</A> and <A HREF="ftp://ftp.cwi.nl/pub/jack/mac">
|
|
||||||
ftp://ftp.cwi.nl/pub/jack/mac</A>.
|
|
||||||
|
|
||||||
<LI> JPEG library by the Independent JPEG Group. A version including
|
|
||||||
Mac projects can be found at Jack's page mentioned above.
|
|
||||||
The most recent JPEG library can always be obtained from <A
|
|
||||||
HREF="ftp://ftp.uu.net/graphics/jpeg/">ftp://ftp.uu.net/graphics/jpeg/</A>.
|
|
||||||
|
|
||||||
<LI> The netpbm/pbmplus, libtiff, zlib and png libraries. The netpbm distribution
|
|
||||||
(which includes libtiff) is generally available on Internet ftp
|
|
||||||
servers. For Python pbmplus, an older incarnation of netpbm, is
|
|
||||||
functionally identical to netpbm, since Python only uses the library
|
|
||||||
and not the complete applications. A distribution with correct
|
|
||||||
projects and library source only is available from, you guessed it, Jack's Mac software
|
|
||||||
page mentioned above.
|
|
||||||
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<H2>Setting Up</H2>
|
|
||||||
|
|
||||||
Now that you have collected everything you should start with building
|
|
||||||
the various parts. If you don't want to fix
|
|
||||||
access paths try to set things up as follows:
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
Top-level-folder:
|
|
||||||
GUSI2
|
|
||||||
imglibs
|
|
||||||
jpeg
|
|
||||||
netpbm
|
|
||||||
libtiff
|
|
||||||
zlib
|
|
||||||
png
|
|
||||||
gdbm
|
|
||||||
Python
|
|
||||||
Modules
|
|
||||||
...
|
|
||||||
Mac
|
|
||||||
Modules
|
|
||||||
Build
|
|
||||||
...
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
If your setup of the libraries is exactly the same as mine (which is
|
|
||||||
not very likely, unless you happen to work from the same CVS
|
|
||||||
repository) you can use the project <code>buildlibs.prj</code> in the
|
|
||||||
<code>:Mac:Build</code> folder to build all needed libraries in one
|
|
||||||
fell swoop, otherwise you will have to build the libraries one by
|
|
||||||
one. <p>
|
|
||||||
|
|
||||||
First build GUSI, the Carbon variant.
|
|
||||||
<p>
|
|
||||||
|
|
||||||
Next, in
|
|
||||||
<code>libjpeg</code>, <code>pbmplus</code>,
|
|
||||||
<code>zlib</code>, <code>libpng</code>, <code>gdbm</code>,
|
|
||||||
and<code>libtiff</code> you build all projects. Usually the projects are in "mac"
|
|
||||||
subfolders, sometimes they are in the main folder. Tcl/tk is a special
|
|
||||||
case, see below.
|
|
||||||
|
|
||||||
<H2>The organization of the Python source tree</H2>
|
|
||||||
|
|
||||||
Time for a short break, while we have a look at the organization of
|
|
||||||
the Python source tree. At the top level, we find the following
|
|
||||||
folders:
|
|
||||||
|
|
||||||
<DL>
|
|
||||||
<DT> Demo
|
|
||||||
<DD> Demo programs that are not Mac-specific. Some of these may not
|
|
||||||
work.
|
|
||||||
|
|
||||||
<DT> Extensions
|
|
||||||
<DD> Extensions to the interpreter that are not Mac-specific. Contains
|
|
||||||
the <code>img</code>, <code>Imaging</code> and <code>Numerical</code> extensions
|
|
||||||
in this distribution.
|
|
||||||
|
|
||||||
<DT> Grammar
|
|
||||||
<DD> The Python grammar. Included for reference only, you cannot build
|
|
||||||
the parser on a Mac.
|
|
||||||
|
|
||||||
<DT> Include
|
|
||||||
<DD> Machine-independent header files.
|
|
||||||
|
|
||||||
<DT> Modules
|
|
||||||
<DD> Machine-independent optional modules. Not all of these will work
|
|
||||||
on the Mac.
|
|
||||||
|
|
||||||
<DT> Lib
|
|
||||||
<DD> Machine-independent modules in Python.
|
|
||||||
|
|
||||||
<DT> Lib:lib-dynload
|
|
||||||
<DD> This is where the dynamically-loaded plugin modules live.
|
|
||||||
|
|
||||||
<DT> Lib:plat-mac
|
|
||||||
<DD> This is where most of the Mac-specific modules live. The modules here
|
|
||||||
are available both in MacPython-OS9 and MacPython-OSX.
|
|
||||||
|
|
||||||
<DT> Objects
|
|
||||||
<DD> Machine-independent code for various object types. Most of these are
|
|
||||||
not really optional: the interpreter will not function without them.
|
|
||||||
|
|
||||||
<DT> Parser
|
|
||||||
<DD> The Python parser (machine-independent).
|
|
||||||
|
|
||||||
<DT> Python
|
|
||||||
<DD> The core interpreter. Most files are machine-independent, some
|
|
||||||
are unix-specific and not used on the Mac.
|
|
||||||
|
|
||||||
<DT> Tools
|
|
||||||
<DD> Tools for python developers. Contains <code>modulator</code> which
|
|
||||||
builds skeleton C extension modules, <code>bgen</code> which generates
|
|
||||||
complete interface modules from information in C header files and
|
|
||||||
<code>freeze</code> which is used to turn Python scripts into real
|
|
||||||
applications (used by MacFreeze and BuildApplication) There are some
|
|
||||||
readme files, but more documentation is sorely needed.
|
|
||||||
|
|
||||||
</DL>
|
|
||||||
|
|
||||||
The mac-specific stuff lives in the <code>Mac</code> folder:
|
|
||||||
<DL>
|
|
||||||
<DT> Build
|
|
||||||
<DD> This is where the project files live and where you build the
|
|
||||||
libraries, shared libraries, executables and plugin modules. All the
|
|
||||||
resulting binaries, except for intermedeate results, are deposited in
|
|
||||||
the toplevel folder or the :Lib:lib-dynload folder (for plugin modules).
|
|
||||||
|
|
||||||
<DT> Compat
|
|
||||||
<DD> Unix-compatability routines. Most of these are not used anymore,
|
|
||||||
since GUSI provides a rather complete emulation, but you may need
|
|
||||||
these if you are trying to build a non-GUSI python.
|
|
||||||
|
|
||||||
<DT> Demo
|
|
||||||
<DD> Mac-specific demo programs, some of them annotated.
|
|
||||||
|
|
||||||
<DT> Include
|
|
||||||
<DD> Mac-specific but compiler-independent include files.
|
|
||||||
|
|
||||||
<DT> Lib
|
|
||||||
<DD> MacPython-OS9 specific standard modules which are not shared with
|
|
||||||
MacPython-OSX.
|
|
||||||
|
|
||||||
<DT> Modules
|
|
||||||
<DD> Mac-specific builtin modules. Theoretically these are all
|
|
||||||
optional, but some are rather essential (like
|
|
||||||
<code>macosmodule</code>). A lot of these modules are generated with
|
|
||||||
<code>bgen</code>, in which case the bgen input files are included so
|
|
||||||
you can attempt to regenerate them or extend them.
|
|
||||||
|
|
||||||
<DT> MPW
|
|
||||||
<DD> MPW-specific files. These have not been used or kept up-to-date
|
|
||||||
for a long time, so use at your own risk.
|
|
||||||
|
|
||||||
<DT> mwerks
|
|
||||||
<DD> Mwerks-specific sources and headers. Contains glue code for
|
|
||||||
Pythons shared-library architecture, a replacement for
|
|
||||||
<code>malloc</code> and a directory with various projects for building
|
|
||||||
variations on the Python interpreter. The <code>mwerks_*.h</code>
|
|
||||||
files here are the option-setting files for the various interpreters
|
|
||||||
and such, comparable to the unix command-line <code>-D</code> options
|
|
||||||
to the compiler. Each project uses the correct option file as its
|
|
||||||
"prefix file" in the "C/C++ language" settings. Disabling optional
|
|
||||||
modules (for the 68K interpreter), building non-GUSI interpreters and
|
|
||||||
various other things are accomplished by modifying these files (and
|
|
||||||
possibly changing the list of files included in the project window, of
|
|
||||||
course).
|
|
||||||
|
|
||||||
<DT> OSX
|
|
||||||
<DD> Specific to MacPython-OSX, not used by MacPython-OS9.
|
|
||||||
|
|
||||||
<DT> OSXResources
|
|
||||||
<DD> Specific to MacPython-OSX, not used by MacPython-OS9.
|
|
||||||
|
|
||||||
<DT> Python
|
|
||||||
<DD> Mac-specific parts of the core interpreter.
|
|
||||||
|
|
||||||
<DT> Resources
|
|
||||||
<DD> Resource files needed to build the interpreter.
|
|
||||||
|
|
||||||
<DT> Scripts
|
|
||||||
<DD> A collection of various mac-specific Python scripts. Some are
|
|
||||||
essential, some are useful but few are documented, so you will have to
|
|
||||||
use your imagination to work them out.
|
|
||||||
|
|
||||||
<DT> Tools
|
|
||||||
<DD> A collection of tools, usually bigger than those in the scripts
|
|
||||||
folder. The important ones here are the IDE and macfreeze. The IDE is built
|
|
||||||
with the buildIDE.py script, which puts the resulting applet in the toplevel
|
|
||||||
folder. Macfreeze is usually invoked through the BuildApplication script,
|
|
||||||
but for more control over the freezing process you can run the main script here.
|
|
||||||
|
|
||||||
|
|
||||||
<DT> Unsupported
|
|
||||||
<DD> Modules that are not supported any longer but may still work with a little effort.
|
|
||||||
</DL>
|
|
||||||
|
|
||||||
<H2>Building the PPC interpreter</H2>
|
|
||||||
|
|
||||||
First you optionally build the external libraries with buildlibs.prj. <p>
|
|
||||||
|
|
||||||
Then, the <code>fullbuild</code> script can be used to build
|
|
||||||
everything, but you need a fully-functional interpreter before you can
|
|
||||||
use it (and one that isn't rebuilt in the process: you cannot rebuild
|
|
||||||
a running program). You could copy the interpreter to a different
|
|
||||||
place and use that to run fullbuild. The <code>PythonStandSmall.prj</code>
|
|
||||||
project builds an interpreter that is suited to this, and it can also come
|
|
||||||
in handy if you need to debug things (which is easier in a static program). <p>
|
|
||||||
|
|
||||||
In case you want to build by hand, or in case the <code>fullbuild</code>
|
|
||||||
script does not work, here is a breakdown of the various projects. <p>
|
|
||||||
|
|
||||||
The projects for interpreter and core library are linked together, so
|
|
||||||
building the PythonInterpreter target
|
|
||||||
in <code>PythonInterpreter.prj</code>
|
|
||||||
will result in the whole core being built, but not the extension modules. <p>
|
|
||||||
|
|
||||||
You will get about 100 warnings on "missing prototype" for the various module init
|
|
||||||
routines, ignore these. You will also get numerous warnings on functions from GUSI which
|
|
||||||
override functions from MSL, ignore these too. <p>
|
|
||||||
|
|
||||||
Here is a breakdown of the projects:
|
|
||||||
|
|
||||||
<DL>
|
|
||||||
|
|
||||||
<DT> PythonCore
|
|
||||||
<DD> The shared library that contains the bulk of the interpreter and
|
|
||||||
its resources.
|
|
||||||
It is a good idea to immedeately put an alias to this
|
|
||||||
shared library in the <code>Extensions</code> folder of your system
|
|
||||||
folder. Do exactly that: put an <em>alias</em> there, copying or
|
|
||||||
moving the file will cause you grief later if you rebuild the library and
|
|
||||||
forget to copy it to the extensions folder again. The ConfigurePythonXXX applets
|
|
||||||
will also do this. <br>
|
|
||||||
|
|
||||||
<DT> PythonInterpeter
|
|
||||||
<DD> The interpreter. This is basically a routine to call out to the
|
|
||||||
shared library. <p>
|
|
||||||
|
|
||||||
<DT> Plugin projects
|
|
||||||
<DD> Each plugin module has a separate project, and these can be rebuilt on
|
|
||||||
the fly. Fullbuild (or actually it's little helper genpluginprojects) takes
|
|
||||||
care of this.
|
|
||||||
</DL>
|
|
||||||
|
|
||||||
After creating the alias to <code>PythonCore</code> you remove any old
|
|
||||||
<code>Python XXXX Preferences</code> file from the <code>Preferences</code> folder
|
|
||||||
(if you had python installed on your system before) and run the interpreter once
|
|
||||||
to create the correct preferences file. <p>
|
|
||||||
|
|
||||||
Next, you have to build the extension modules.
|
|
||||||
If you don't use fullbuild simply open each project and build it.
|
|
||||||
<p>
|
|
||||||
|
|
||||||
Finally, you must build the standard applets:
|
|
||||||
<code>EditPythonPrefs</code>, <code>BuildApplet</code>, etc. For the N-th time:
|
|
||||||
fullbuild does this for you, but you can also manually drag/drop them onto
|
|
||||||
BuildApplet. <p>
|
|
||||||
|
|
||||||
You are all set now, and should read the release notes and
|
|
||||||
<code>ReadMe</code> file from the <code>Mac</code> folder.
|
|
||||||
|
|
||||||
Rebuilding .exp files is no longer needed since CodeWarrior 7.
|
|
||||||
|
|
||||||
<H2><a name="cvs">Using the CVS source archive</a></H2>
|
|
||||||
|
|
||||||
It is possible (and probably best) to access the Python sources through remote CVS. The
|
|
||||||
advantage of this is that you get the very latest sources, so any bug
|
|
||||||
fixed or new features will be immedeately available. This is also the
|
|
||||||
disadvantage, of course: as this is the same tree as is used for
|
|
||||||
development it may sometimes be a little less stable. <p>
|
|
||||||
|
|
||||||
The CVS client of choice is Alexandre Parenteau's MacCVS. It can be
|
|
||||||
obtained through the <a href="http://www.wincvs.org">WinCVS
|
|
||||||
homepage</a>. MacCVS uses Internet Config to set file types correctly
|
|
||||||
based on the filename extension. In the maccvs preferences you should
|
|
||||||
also set (in the "binary files" section) "use mac encoding:
|
|
||||||
applesingle" and (in the "text files" section) "use ISO latin 1
|
|
||||||
conversion". <p>
|
|
||||||
|
|
||||||
It is a good idea to disable Quicktime Exchange in the Quicktime control
|
|
||||||
panel if you are on OS9 or before. Quicktime Exchange will magically map
|
|
||||||
some extensions to filetypes, and this can seriously hinder you if, for
|
|
||||||
instance, <code>.bmp</code> is not a Windows bitmap file. <p>
|
|
||||||
|
|
||||||
The Python sources are checked out from the main
|
|
||||||
Python CVS archive on sourceforge.net, see the <a
|
|
||||||
href="http://www.python.org/download/cvs.html">Source access via
|
|
||||||
CVS</a> page for details. When you check the sources out you will get
|
|
||||||
something like <code>Python:dist:src</code>, and under that the
|
|
||||||
<code>Modules</code>, <code>Lib</code>, <code>Mac</code> etc hierarchy. The
|
|
||||||
<code>src</code> folder can be renamed to <code>Python</code>, and
|
|
||||||
is what this document refers to as the "toplevel Python folder". <P>
|
|
||||||
|
|
||||||
The CVS repository does not contain all the projects for the plugin modules,
|
|
||||||
these are built with <code>fullbuild.py</code> normally. For this reason
|
|
||||||
it is probably a good idea to first build <code>PythonStandSmall.prj</code>,
|
|
||||||
which builds a fairly minimal interpreter, and then follow the
|
|
||||||
fullbuild instructions</a>.
|
|
||||||
|
|
||||||
<H2>Odds and ends</H2>
|
|
||||||
|
|
||||||
Some remarks that I could not fit in elsewhere:
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
|
|
||||||
<LI> It may be possible to use the <code>PythonCore</code> shared
|
|
||||||
library to embed Python in another program, if your program can live
|
|
||||||
with using GUSI for I/O. Use PythonCore in stead of your MSL C library
|
|
||||||
(or, at the very least, link it before the normal C library). Ask for help
|
|
||||||
on PythonMac-SIG if you have problems with this.
|
|
||||||
|
|
||||||
<LI> <a name="extending"></a>It is possible to build PPC extension
|
|
||||||
modules without building a complete Python. The binary distribution
|
|
||||||
installer can optionally install all the needed folders (the develop
|
|
||||||
option). A template for a dynamic module can be found in
|
|
||||||
<code>xx.prj</code>.
|
|
||||||
|
|
||||||
<LI> The Python shared library architecture is a variant of the architecture
|
|
||||||
described as "application with shared libraries and dropins" in the MetroWerks
|
|
||||||
"Targeting MacOS" documentation. The Python Application and applet-template use
|
|
||||||
the <code>MSL AppRuntime.Lib</code> runtime library (with properly set CFM
|
|
||||||
initialization and termination routines). PythonCore uses <code>MSL Runtime.Lib</code>,
|
|
||||||
which is really intended for standalone programs but which we fool into working by
|
|
||||||
providing a dummy main program.
|
|
||||||
It is linked statically into PythonCore (and exported to the applications and plugins)
|
|
||||||
so we do not have to distribute yet another shared library. Plugin modules use
|
|
||||||
<code>MSL ShlibRuntime.Lib</code> (not the dropin runtime: modules are never unloaded)
|
|
||||||
and obtain the rest from PythonCore. PythonCore uses a
|
|
||||||
non-standard initialization entry point, <code>__initialize_with_resources</code>, to
|
|
||||||
be able to obtain resources from the library file later on. Plugins can do the same
|
|
||||||
(_tkinter does) or use the standard <code>__initialize</code> entry point.
|
|
||||||
|
|
||||||
|
|
||||||
</UL>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
|
@ -1,90 +0,0 @@
|
||||||
<HTML><HEAD><TITLE>Using python to create CGI scripts</TITLE></HEAD>
|
|
||||||
<BODY>
|
|
||||||
<H1>Using python to create CGI scripts</H1>
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
In this document we will (eventually) explain how to create Python CGI scripts
|
|
||||||
for use with Personal WebServer, WebStar and probably other Mac-based HTTP servers too.
|
|
||||||
Since CGI scripts are AppleEvent servers on the mac we will also learn
|
|
||||||
a little about general AppleEvent server programming and about applet
|
|
||||||
debugging. <p>
|
|
||||||
|
|
||||||
<blockquote>Note that the current setup is very preliminary, and hence
|
|
||||||
itis probably not wise to base your strategic products on the information
|
|
||||||
in this document:-) In stead, play with the code here and join the
|
|
||||||
<a href="mailto:pythonmac-sig-request@python.org">pythonmac-sig</a>, where
|
|
||||||
we I would like to have a discussion on a real design for a Mac CGI framework
|
|
||||||
(preferrably something that will make CGI scripts portable to unix and other
|
|
||||||
platforms).
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h2>AppleEvent servers</h2>
|
|
||||||
|
|
||||||
Since AppleEvent clients are easier to write and understand than servers
|
|
||||||
you should probably read the section on <a href="applescript.html">Open Scripting
|
|
||||||
clients in Python</a> first. <p>
|
|
||||||
|
|
||||||
Next, let us have a look at the AE Server framework,
|
|
||||||
<a href="../Lib/toolbox/MiniAEFrame.py">MiniAEFrame.py</a>.
|
|
||||||
This file contains two classes, <code>MiniApplication</code> and <code>AEServer</code>.
|
|
||||||
MiniApplication is a tiny replacement for <code>FrameWork.Application</code>,
|
|
||||||
suitable if your application does not need windows and such.
|
|
||||||
|
|
||||||
AEServer is a bit of glue that does part of the appleevent decoding for you. You
|
|
||||||
call <code>installaehandler</code> passing it the class and id (4-char strings)
|
|
||||||
of the event you have a handler for and the handler callback routine. When the
|
|
||||||
appleevent occurs your callback is called with the right arguments. For now,
|
|
||||||
your argument names are the 4-char values used internally by Open Scripting,
|
|
||||||
eventually there will be a translation similar to what the generated OSA client
|
|
||||||
suites provide. <p>
|
|
||||||
|
|
||||||
You can test AEServer by double-clicking it. It will react to the standard
|
|
||||||
run/open/print/quit OSA commands. If it is running as a normal python script and you
|
|
||||||
drag a file onto the interpreter the script will tell you what event it got. <p>
|
|
||||||
|
|
||||||
<h2>A Minimal CGI script</h2>
|
|
||||||
|
|
||||||
To try a CGI script you will first need a http server. Apple's Personal Webserver
|
|
||||||
is fine, but I have also used the
|
|
||||||
shareware
|
|
||||||
<a href="http://www.stairways.com/netpresenz/">NetPresenz</a>
|
|
||||||
by Peter Lewis
|
|
||||||
(don't forget to pay if you give it more than a test run!). Install your
|
|
||||||
http server, and make sure that it can serve textual documents. <p>
|
|
||||||
|
|
||||||
Next, let us have a look at our example CGI scripts. CGI scripts have to be
|
|
||||||
applications, so we will have to make an applet as explained in
|
|
||||||
<a href="example2.html">example 2</a>. Our applet code,
|
|
||||||
<a href="cgi/cgitest.cgi.py">cgitest.cgi.py</a> is a rather minimal <code>execfile</code>
|
|
||||||
statement. The reason for this is debugging: the real code is in
|
|
||||||
<a href="cgi/realcgitest.py">realcgitest.py</a>, and this way you do not have
|
|
||||||
to run mkapplet again every time you change the code. Rename realcgitest.py
|
|
||||||
to cgitest.cgi.py once you are satisfied that it works. <p>
|
|
||||||
|
|
||||||
The resource file is not very special, with one exception: since we want to do
|
|
||||||
our own appleevent handling we don't want the Python initialization code to
|
|
||||||
create argc and argv for use, since this might gobble up any appleevents we are
|
|
||||||
interested in. For this reason we have included a 'Popt' resource that disables
|
|
||||||
the argv initialization. An easy way to create this resource is to drop
|
|
||||||
the <code>.rsrc</code> file (or the finished applet, if you like) onto
|
|
||||||
<code>EditPythonPrefs</code> and set the "no argv processing" option. <p>
|
|
||||||
|
|
||||||
The code itself is actually not too complicated either. We install handlers
|
|
||||||
for "open application" and "quit" (stolen from the test code in MiniAEFrame)
|
|
||||||
and the <code>"WWW\275"/"sdoc"</code> event, the event sent on CGI execution.
|
|
||||||
The cgi handler pretty-prints the CGI arguments in HTML and returns the whole
|
|
||||||
string that is to be passed to the client. The actual parameters passed
|
|
||||||
are explained in <a href="http://www.biap.com/datapig/mrwheat/cgi_params.html">
|
|
||||||
http://www.biap.com/datapig/mrwheat/cgi_params.html</a>. <p>
|
|
||||||
|
|
||||||
To test the script drop <code>cgitest.cgi.py</code> onto <code>mkapplet</code>,
|
|
||||||
move the resulting <code>cgitest.cgi</code> to somewhere where it is reachable
|
|
||||||
by NetPresenz, and point your web browser towards it. Note that this assume you have
|
|
||||||
already renamed realcgitest.py to cgitest.cgi.py, otherwise you'll also have
|
|
||||||
to copy that file along. <p>
|
|
||||||
|
|
||||||
For Apple's Personal Webserver you need to do a bit more: you have to copy the
|
|
||||||
cgi applet to somewhere in your "Webpages" folder and you have to tell the webserver
|
|
||||||
(in the control panels) that your CGI script exists. I don't understand what the various
|
|
||||||
types of cgi scripts mean, but experiment with them.
|
|
||||||
</BODY></HTML>
|
|
|
@ -1,2 +0,0 @@
|
||||||
# Debug applets quickly.
|
|
||||||
execfile('realcgitest.py')
|
|
Binary file not shown.
|
@ -1,59 +0,0 @@
|
||||||
"""cgitest - A minimal CGI applet. Echos parameters back to the client.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from MiniAEFrame import AEServer, MiniApplication
|
|
||||||
import MacOS
|
|
||||||
|
|
||||||
debug=1
|
|
||||||
|
|
||||||
class CGITest(AEServer, MiniApplication):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
MiniApplication.__init__(self)
|
|
||||||
AEServer.__init__(self)
|
|
||||||
self.installaehandler('aevt', 'oapp', self.open_app)
|
|
||||||
self.installaehandler('aevt', 'quit', self.quit)
|
|
||||||
self.installaehandler('WWW\275', 'sdoc', self.cgihandler)
|
|
||||||
if debug:
|
|
||||||
self.installaehandler('****', '****', self.otherhandler)
|
|
||||||
oldparams = MacOS.SchedParams(0, 0)
|
|
||||||
self.mainloop()
|
|
||||||
apply(MacOS.SchedParams, oldparams)
|
|
||||||
|
|
||||||
def quit(self, **args):
|
|
||||||
self.quitting = 1
|
|
||||||
|
|
||||||
def open_app(self, **args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def otherhandler(self, *args, **kwargs):
|
|
||||||
print 'Unknown AppleEvent'
|
|
||||||
print 'args', args
|
|
||||||
print 'kwargs', kwargs
|
|
||||||
|
|
||||||
def cgihandler(self, pathargs, **args):
|
|
||||||
if debug:
|
|
||||||
print 'CGI request', pathargs, args
|
|
||||||
rv = """HTTP/1.0 200 OK
|
|
||||||
Server: Unknown; python-cgi-script
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-type: text/html
|
|
||||||
|
|
||||||
<title>Python CGI-script results</title>
|
|
||||||
<h1>Python CGI-script results</h1>
|
|
||||||
<hr>
|
|
||||||
"""
|
|
||||||
rv = rv+'<br><b>Direct object:</b> %s\n'%pathargs
|
|
||||||
|
|
||||||
for key in args.keys():
|
|
||||||
if key[0] != '_':
|
|
||||||
rv = rv + '<br><b>%s:</b> %s\n'%(key, args[key])
|
|
||||||
rv = rv +'<hr>\nSee you next time!\n'
|
|
||||||
|
|
||||||
# Note: if you want to quit after each request enable the line
|
|
||||||
# self.quitting = 1
|
|
||||||
|
|
||||||
return rv
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
CGITest()
|
|
|
@ -1,44 +0,0 @@
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<TITLE>Embedding Python on the Mac</TITLE>
|
|
||||||
</HEAD>
|
|
||||||
<BODY>
|
|
||||||
<H1>Embedding Python on the Mac</H1>
|
|
||||||
<HR>
|
|
||||||
<B>Note</B>: if you have a binary-only release of MacPython you will not
|
|
||||||
have this demo installed. Install the developer option (in the standard installer) or
|
|
||||||
a source release if you want to embed
|
|
||||||
Python in other applications. <p>
|
|
||||||
|
|
||||||
Embedding Python on the mac is pretty similar to embedding it on other
|
|
||||||
platforms, but a few points need mentioning:
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
<LI> You call <CODE>PyMac_Initialize()</CODE> in stead of
|
|
||||||
<CODE>Py_Initialize()</CODE>. The prototype is in <CODE>macglue.h</CODE>.
|
|
||||||
This call initializes the toolbox, GUSI (if needed), sets up the correct
|
|
||||||
resource files and calls Py_Initialize.
|
|
||||||
|
|
||||||
<LI> You have to be consequent in your use of GUSI. If the library uses
|
|
||||||
it so should your program and vice versa.
|
|
||||||
|
|
||||||
<LI> The console-behaviour (close-on-exit, etc) is controlled by Python
|
|
||||||
but you can overwrite this with <code>PyMac_SetConsoleHandler()</code>.
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
The Python environment is started with a dummy argc and argv, and initial
|
|
||||||
startup options are obtained through the usual means, except that the
|
|
||||||
user pression the option-key will not result in an interactive dialog.
|
|
||||||
You can, however, set startup options on your program in the same way as you
|
|
||||||
do for applets, by dragging your application to <code>EditPythonPrefs</code>. <p>
|
|
||||||
|
|
||||||
The most logical way to embed Python is to link it against the shared
|
|
||||||
library <code>PythonCore</code>. An example project and source can be
|
|
||||||
found in the <a href="embed">embed</a> folder. <p>
|
|
||||||
|
|
||||||
This example code also shows how to override the console: if you pass the
|
|
||||||
<code>-q</code> argument in the argument box output is thrown away. If you
|
|
||||||
pass the <code>-d</code> option the output is sent to <code>DebugStr</code>
|
|
||||||
(so be sure to use this only when running the example under a debugger).
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
|
@ -1,71 +0,0 @@
|
||||||
/* Example of embedding Python in another program */
|
|
||||||
|
|
||||||
#include "Python.h"
|
|
||||||
#include "macglue.h"
|
|
||||||
|
|
||||||
static char *argv0;
|
|
||||||
|
|
||||||
long my_writehandler(char *buf, long count)
|
|
||||||
{
|
|
||||||
long mycount;
|
|
||||||
unsigned char mybuf[255];
|
|
||||||
|
|
||||||
mycount = count;
|
|
||||||
if (mycount > 255 ) mycount = 255;
|
|
||||||
mybuf[0] = (unsigned char)mycount;
|
|
||||||
strncpy((char *)mybuf+1, buf, mycount);
|
|
||||||
DebugStr(mybuf);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
main(argc, argv)
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
/* So the user can set argc/argv to something interesting */
|
|
||||||
argc = ccommand(&argv);
|
|
||||||
/* Save a copy of argv0 */
|
|
||||||
argv0 = argv[0];
|
|
||||||
|
|
||||||
/* If the first option is "-q" we don't open a console */
|
|
||||||
if ( argc > 1 && strcmp(argv[1], "-q") == 0 ) {
|
|
||||||
PyMac_SetConsoleHandler(PyMac_DummyReadHandler, PyMac_DummyWriteHandler,
|
|
||||||
PyMac_DummyWriteHandler);
|
|
||||||
} else
|
|
||||||
if ( argc > 1 && strcmp(argv[1], "-d") == 0 ) {
|
|
||||||
PyMac_SetConsoleHandler(PyMac_DummyReadHandler, my_writehandler,
|
|
||||||
my_writehandler);
|
|
||||||
}
|
|
||||||
/* Initialize the Python interpreter. Required. */
|
|
||||||
PyMac_Initialize();
|
|
||||||
|
|
||||||
/* Define sys.argv. It is up to the application if you
|
|
||||||
want this; you can also let it undefined (since the Python
|
|
||||||
code is generally not a main program it has no business
|
|
||||||
touching sys.argv...) */
|
|
||||||
PySys_SetArgv(argc, argv);
|
|
||||||
|
|
||||||
/* Do some application specific code */
|
|
||||||
printf("Hello, brave new world\n\n");
|
|
||||||
|
|
||||||
/* Execute some Python statements (in module __main__) */
|
|
||||||
PyRun_SimpleString("import sys\n");
|
|
||||||
PyRun_SimpleString("print sys.builtin_module_names\n");
|
|
||||||
PyRun_SimpleString("print sys.argv\n");
|
|
||||||
|
|
||||||
/* Note that you can call any public function of the Python
|
|
||||||
interpreter here, e.g. call_object(). */
|
|
||||||
|
|
||||||
/* Some more application specific code */
|
|
||||||
printf("\nGoodbye, cruel world\n");
|
|
||||||
/* Exit, cleaning up the interpreter */
|
|
||||||
Py_Exit(0);
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is called by the interpreter to get its own name */
|
|
||||||
char *
|
|
||||||
getprogramname()
|
|
||||||
{
|
|
||||||
return argv0;
|
|
||||||
}
|
|
Binary file not shown.
|
@ -1,151 +0,0 @@
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<TITLE>Creating standalone applications with Python</TITLE>
|
|
||||||
</HEAD>
|
|
||||||
<BODY>
|
|
||||||
<H1>Creating standalone applications with Python</H1>
|
|
||||||
|
|
||||||
With <a href="example2.html#applet">BuildApplet</a> you can build a standalone
|
|
||||||
Python application that works like
|
|
||||||
any other Mac application: you can double-click it, run it while the
|
|
||||||
Python interpreter is running other scripts, drop files on it, etc. It is, however,
|
|
||||||
still dependent on the whole Python installation on your machine: the PythonCore
|
|
||||||
engine, the plugin modules and the various Lib folders.<p>
|
|
||||||
|
|
||||||
In some cases you may want to create a true application, for instance because
|
|
||||||
you want to send it off to people who may not have Python installed on their
|
|
||||||
machine, or because you the application is important and you do not want changes
|
|
||||||
in your Python installation like new versions to influence it.
|
|
||||||
|
|
||||||
<H2>The easy way</H2>
|
|
||||||
|
|
||||||
The easiest way to create an application from a Python script is simply by dropping
|
|
||||||
it on the <code>BuildApplication</code> applet in the main Python folder.
|
|
||||||
BuildApplication has a similar interface as BuildApplet: you drop a script on
|
|
||||||
it and it will process it, along with an optional <code>.rsrc</code> file.
|
|
||||||
<P>
|
|
||||||
|
|
||||||
What BuildApplication does, however, is very different. It parses your script,
|
|
||||||
recursively looking for all modules you use, bundles the compiled code for
|
|
||||||
all these modules in PYC resources, adds the executable machine code for the
|
|
||||||
PythonCore engine, any dynamically loaded modules you use and a main program, combines
|
|
||||||
all this into a single file and adds a few preference resources (which you
|
|
||||||
can inspect with <code>EditPythonPrefs</code>, incidentally) to isolate the
|
|
||||||
new program from the existing Python installation.<P>
|
|
||||||
|
|
||||||
Usually you do not need to worry about all this, but occasionally you may have
|
|
||||||
to exercise some control over the process, for instance because your
|
|
||||||
program imports modules that don't exist (which can happen if your script
|
|
||||||
is multi-platform and those modules will never be used on the Mac). See
|
|
||||||
the section on <a href="#directives">directives</a> below for details.
|
|
||||||
If you get strange error messages about missing modules it may also be worthwhile
|
|
||||||
to run macfreeze in report mode on your program, see below.
|
|
||||||
<P>
|
|
||||||
|
|
||||||
<H2>Doing it the hard way</H2>
|
|
||||||
|
|
||||||
With the <EM>macfreeze</EM> script, for which BuildApplication is a simple
|
|
||||||
wrapper, you can go a step further and create CodeWarrior projects and
|
|
||||||
sourcefiles which can then be used to build your final application. While
|
|
||||||
BuildApplication is good enough for 90% of the use cases there are situations
|
|
||||||
where you need macfreeze itself, mainly if you want to embed your frozen Python
|
|
||||||
script into an existing C application, or when you need the extra bit of speed:
|
|
||||||
the resulting application will start up a bit quicker than one generated
|
|
||||||
with BuildApplication. <p>
|
|
||||||
|
|
||||||
When you start
|
|
||||||
<code>Mac:Tools:macfreeze:macfreeze.py</code> you are asked for the
|
|
||||||
script file, and you can select which type of freeze to do. The first
|
|
||||||
time you should always choose <em>report only</em>, which will produce a
|
|
||||||
listing of modules and where they are included from in the console
|
|
||||||
window. Macfreeze actually parses all modules, so it may crash in the
|
|
||||||
process. If it does try again with a higher debug value, this should
|
|
||||||
show you where it crashes. <p>
|
|
||||||
|
|
||||||
<h2><a name="directives">Directives</a></h2>
|
|
||||||
|
|
||||||
For more elaborate programs you will often see that freeze includes
|
|
||||||
modules you don't need (because they are for a different platform, for
|
|
||||||
instance) or that it cannot find all your modules (because you modify
|
|
||||||
<code>sys.path</code> early in your initialization). It is possible to
|
|
||||||
include directives to tell macfreeze to add items to the search path and
|
|
||||||
include or exclude certain modules. All your directives should be in the
|
|
||||||
main script file. <p>
|
|
||||||
|
|
||||||
Directives have the following form:
|
|
||||||
<pre>
|
|
||||||
# macfreeze: command argument
|
|
||||||
</pre>
|
|
||||||
The trigger <code>macfreeze:</code> must be spelled exactly like that,
|
|
||||||
but the whitespace can be any combination of spaces and tabs. Macfreeze
|
|
||||||
understands the following directives:
|
|
||||||
|
|
||||||
<DL>
|
|
||||||
<DT> <code>path</code>
|
|
||||||
<DD> Prepend a folder to <code>sys.path</code>. The argument is a
|
|
||||||
pathname, which should probably be relative (starting with a colon) and
|
|
||||||
is interpreted relative to the folder where the script lives.
|
|
||||||
|
|
||||||
<DT> <code>include</code>
|
|
||||||
<DD> Include a module. The module can either be given by filename or by
|
|
||||||
module name, in which case it is looked up through the normal method.
|
|
||||||
|
|
||||||
<DT> <code>exclude</code>
|
|
||||||
<DD> Exclude a module. The module must be given by modulename. Even when
|
|
||||||
freeze deems the module necessary it will not be included in the
|
|
||||||
application.
|
|
||||||
|
|
||||||
<DT> <code>optional</code>
|
|
||||||
<DD> Include a module if it can be found, but don't complain if it can't.
|
|
||||||
|
|
||||||
</DL>
|
|
||||||
|
|
||||||
There is actually a fourth way that macfreeze can operate: it can be used
|
|
||||||
to generate only the resource file containing the compiled <code>PYC</code>
|
|
||||||
resources. This may be useful if you have embedded Python in your own
|
|
||||||
application. The resource file generated is the same as for the CodeWarrior
|
|
||||||
generation process. <p>
|
|
||||||
|
|
||||||
<h2>Freezing with CodeWarrior</h2>
|
|
||||||
|
|
||||||
To freeze with CodeWarrior you need CodeWarrior, obviously, and a full
|
|
||||||
source distribution of Python. You select the <em>Codewarrior source and
|
|
||||||
project</em> option. You specify an output folder, which is by default
|
|
||||||
the name of your script with <code>.py</code> removed and
|
|
||||||
<code>build.</code> prepended. If the output folder does not exist yet
|
|
||||||
it is created, and a template project file and bundle resource file are
|
|
||||||
deposited there. Next, a source file <code>macfreezeconfig.c</code> is
|
|
||||||
created which includes all builtin modules your script uses, and a
|
|
||||||
resource file <code>frozenmodules.rsrc</code> which contains the
|
|
||||||
<code>PYC</code> resources for all your Python modules. <p>
|
|
||||||
|
|
||||||
The project expects to live in a folder one level below the Python root
|
|
||||||
folder, so the next thing you should do is move the build folder there.
|
|
||||||
It is a good idea to leave an alias with the same name in the original
|
|
||||||
location: when you run freeze again it will regenerate the
|
|
||||||
<code>frozenmodules.rsrc</code> file but not the project and bundle
|
|
||||||
files. This is probably what you want: if you modify your python sources
|
|
||||||
you have to re-freeze, but you may have changed the project and bundle
|
|
||||||
files, so you don't want to regenerate them. <p>
|
|
||||||
|
|
||||||
An alternative is to leave the build folder where it is, but then you
|
|
||||||
have to adapt the search path in the project. <p>
|
|
||||||
|
|
||||||
The project is set up to include all the standard builtin modules, but
|
|
||||||
the CW linker is smart enough to exclude any object code that isn't
|
|
||||||
referenced. Still, it may be worthwhile to remove any sources for
|
|
||||||
modules that you are sure are not used to cut back on compilation time.
|
|
||||||
You may also want to examine the various resource files (for Tcl/Tk, for
|
|
||||||
instance): the loader has no way to know that these aren't used. <p>
|
|
||||||
|
|
||||||
You may also need to add sourcefiles if your script uses non-standard
|
|
||||||
builtin modules, like anything from the <code>Extensions</code> folder. <p>
|
|
||||||
|
|
||||||
The <code>frozenbundle.rsrc</code> resource file contains the bundle
|
|
||||||
information. It is almost identical to the bundle file used for applets,
|
|
||||||
with the exception that it sets the <code>sys.path</code> initialization
|
|
||||||
to <code>$(APPLICATION)</code> only. This means that all modules will only
|
|
||||||
be looked for in PYC resources in your application. <p>
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
** InterslipLib - Routines to talk to InterSLIP. Version 1.1, 31-Oct-1995.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** (c) Jack Jansen, CWI, 1995 <jack@cwi.nl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Devices.h>
|
|
||||||
|
|
||||||
#include "InterslipLib.h"
|
|
||||||
|
|
||||||
static CntrlParam iopb;
|
|
||||||
static short refnum = -1;
|
|
||||||
|
|
||||||
OSErr is_open()
|
|
||||||
{
|
|
||||||
if ( refnum >= 0 ) return 0;
|
|
||||||
return OpenDriver("\p.InterSLIP", &refnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
OSErr is_connect()
|
|
||||||
{
|
|
||||||
iopb.ioCRefNum = refnum;
|
|
||||||
iopb.ioVRefNum = refnum;
|
|
||||||
iopb.ioCompletion = (UniversalProcPtr) 0;
|
|
||||||
iopb.csCode = 2;
|
|
||||||
return PBControlImmed((ParmBlkPtr)&iopb);
|
|
||||||
}
|
|
||||||
|
|
||||||
OSErr is_disconnect()
|
|
||||||
{
|
|
||||||
iopb.ioCRefNum = refnum;
|
|
||||||
iopb.ioVRefNum = refnum;
|
|
||||||
iopb.ioCompletion = (UniversalProcPtr) 0;
|
|
||||||
iopb.csCode = 3;
|
|
||||||
return PBControlImmed((ParmBlkPtr)&iopb);
|
|
||||||
}
|
|
||||||
|
|
||||||
OSErr is_status(long *status, long *msgseqnum, StringPtr *msg)
|
|
||||||
{
|
|
||||||
long *csp;
|
|
||||||
OSErr err;
|
|
||||||
|
|
||||||
iopb.ioCRefNum = refnum;
|
|
||||||
iopb.ioVRefNum = refnum;
|
|
||||||
iopb.ioCompletion = (UniversalProcPtr) 0;
|
|
||||||
iopb.csCode = 4;
|
|
||||||
if( err = PBControlImmed((ParmBlkPtr)&iopb) )
|
|
||||||
return err;
|
|
||||||
csp = (long *)&iopb.csParam;
|
|
||||||
*status = csp[0];
|
|
||||||
*msgseqnum = csp[1];
|
|
||||||
*msg = (unsigned char *)csp[2];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSErr is_getconfig(long *baudrate, long *flags,
|
|
||||||
Str255 idrvnam, Str255 odrvnam, Str255 cfgnam)
|
|
||||||
{
|
|
||||||
long *csp;
|
|
||||||
OSErr err;
|
|
||||||
|
|
||||||
iopb.ioCRefNum = refnum;
|
|
||||||
iopb.ioVRefNum = refnum;
|
|
||||||
iopb.ioCompletion = (UniversalProcPtr) 0;
|
|
||||||
iopb.csCode = 6;
|
|
||||||
csp = (long *)&iopb.csParam;
|
|
||||||
csp[2] = (long)idrvnam;
|
|
||||||
csp[3] = (long)odrvnam;
|
|
||||||
csp[4] = (long)cfgnam;
|
|
||||||
if( err = PBControlImmed((ParmBlkPtr)&iopb) )
|
|
||||||
return err;
|
|
||||||
*baudrate = csp[0];
|
|
||||||
*flags = csp[1];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSErr is_setconfig(long baudrate, long flags,
|
|
||||||
Str255 idrvnam, Str255 odrvnam, Str255 cfgnam)
|
|
||||||
{
|
|
||||||
long *csp;
|
|
||||||
OSErr err;
|
|
||||||
|
|
||||||
iopb.ioCRefNum = refnum;
|
|
||||||
iopb.ioVRefNum = refnum;
|
|
||||||
iopb.ioCompletion = (UniversalProcPtr) 0;
|
|
||||||
iopb.csCode = 7;
|
|
||||||
csp = (long *)&iopb.csParam;
|
|
||||||
csp[0] = baudrate;
|
|
||||||
csp[1] = flags;
|
|
||||||
csp[2] = (long)idrvnam;
|
|
||||||
csp[3] = (long)odrvnam;
|
|
||||||
csp[4] = (long)cfgnam;
|
|
||||||
return PBControlImmed((ParmBlkPtr)&iopb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
** InterSLIP API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Types.h>
|
|
||||||
|
|
||||||
/* States */
|
|
||||||
#define IS_IDLE 0
|
|
||||||
#define IS_WMODEM 1
|
|
||||||
#define IS_DIAL 2
|
|
||||||
#define IS_LOGIN 3
|
|
||||||
#define IS_RUN 4
|
|
||||||
#define IS_DISC 5
|
|
||||||
|
|
||||||
OSErr is_open(); /* Open InterSLIP driver (optional) */
|
|
||||||
OSErr is_connect();/* Connect */
|
|
||||||
OSErr is_disconnect(); /* Disconnect */
|
|
||||||
OSErr is_status(long *, long *, StringPtr *); /* Get status, msg seq#, msg pointer */
|
|
||||||
OSErr is_getconfig(long *, long *, Str255 , Str255 , Str255 ); /* get config */
|
|
||||||
OSErr is_setconfig(long , long , Str255 , Str255 , Str255 ); /* set config */
|
|
|
@ -1,225 +0,0 @@
|
||||||
/***********************************************************
|
|
||||||
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
|
|
||||||
The Netherlands.
|
|
||||||
|
|
||||||
All Rights Reserved
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software and its
|
|
||||||
documentation for any purpose and without fee is hereby granted,
|
|
||||||
provided that the above copyright notice appear in all copies and that
|
|
||||||
both that copyright notice and this permission notice appear in
|
|
||||||
supporting documentation, and that the names of Stichting Mathematisch
|
|
||||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
|
||||||
distribution of the software without specific, written prior permission.
|
|
||||||
|
|
||||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
|
||||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
|
||||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
||||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
******************************************************************/
|
|
||||||
|
|
||||||
#include "Python.h"
|
|
||||||
#include "InterslipLib.h"
|
|
||||||
#include "macglue.h"
|
|
||||||
|
|
||||||
static PyObject *ErrorObject;
|
|
||||||
|
|
||||||
/* ----------------------------------------------------- */
|
|
||||||
|
|
||||||
static char pyis_open__doc__[] =
|
|
||||||
"Load the interslip driver (optional)"
|
|
||||||
;
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
pyis_open(self, args)
|
|
||||||
PyObject *self; /* Not used */
|
|
||||||
PyObject *args;
|
|
||||||
{
|
|
||||||
OSErr err;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
err = is_open();
|
|
||||||
if ( err ) {
|
|
||||||
PyErr_Mac(ErrorObject, err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Py_INCREF(Py_None);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char pyis_connect__doc__[] =
|
|
||||||
"Tell the driver to start a connect"
|
|
||||||
;
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
pyis_connect(self, args)
|
|
||||||
PyObject *self; /* Not used */
|
|
||||||
PyObject *args;
|
|
||||||
{
|
|
||||||
OSErr err;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
err = is_connect();
|
|
||||||
if ( err ) {
|
|
||||||
PyErr_Mac(ErrorObject, err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Py_INCREF(Py_None);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char pyis_disconnect__doc__[] =
|
|
||||||
"Tell the interslip driver to start a disconnect"
|
|
||||||
;
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
pyis_disconnect(self, args)
|
|
||||||
PyObject *self; /* Not used */
|
|
||||||
PyObject *args;
|
|
||||||
{
|
|
||||||
OSErr err;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
err = is_disconnect();
|
|
||||||
if ( err ) {
|
|
||||||
PyErr_Mac(ErrorObject, err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Py_INCREF(Py_None);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char pyis_status__doc__[] =
|
|
||||||
"Return (numeric_status, message_seqnum, message_string) status tuple"
|
|
||||||
;
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
pyis_status(self, args)
|
|
||||||
PyObject *self; /* Not used */
|
|
||||||
PyObject *args;
|
|
||||||
{
|
|
||||||
long status, seqnum;
|
|
||||||
StringPtr message;
|
|
||||||
OSErr err;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
err = is_status(&status, &seqnum, &message);
|
|
||||||
if ( err ) {
|
|
||||||
PyErr_Mac(ErrorObject, err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return Py_BuildValue("iiO&", (int)status, (int)seqnum, PyMac_BuildStr255, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char pyis_getconfig__doc__[] =
|
|
||||||
"Return configuration data (ibaud, obaud, flags, idrvname, odrvname, cfgname)"
|
|
||||||
;
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
pyis_getconfig(self, args)
|
|
||||||
PyObject *self; /* Not used */
|
|
||||||
PyObject *args;
|
|
||||||
{
|
|
||||||
long baudrate, flags;
|
|
||||||
Str255 idrvname, odrvname, cfgname;
|
|
||||||
OSErr err;
|
|
||||||
int ibaud, obaud;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
|
||||||
return NULL;
|
|
||||||
err = is_getconfig(&baudrate, &flags, idrvname, odrvname, cfgname);
|
|
||||||
if ( err ) {
|
|
||||||
PyErr_Mac(ErrorObject, err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ibaud = (baudrate >> 16) & 0xffff;
|
|
||||||
obaud = baudrate & 0xffff;
|
|
||||||
return Py_BuildValue("iiiO&O&O&", ibaud, obaud, (int)flags, PyMac_BuildStr255, idrvname,
|
|
||||||
PyMac_BuildStr255, odrvname, PyMac_BuildStr255, cfgname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char pyis_setconfig__doc__[] =
|
|
||||||
"Set configuration data (ibaud, obaud, flags, idrvname, odrvname, cfgname)"
|
|
||||||
;
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
pyis_setconfig(self, args)
|
|
||||||
PyObject *self; /* Not used */
|
|
||||||
PyObject *args;
|
|
||||||
{
|
|
||||||
long baudrate;
|
|
||||||
int flags;
|
|
||||||
Str255 idrvname, odrvname, cfgname;
|
|
||||||
OSErr err;
|
|
||||||
int ibaud, obaud;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iiiO&O&O&", &ibaud, &obaud, &flags, PyMac_GetStr255, idrvname,
|
|
||||||
PyMac_GetStr255, odrvname, PyMac_GetStr255, cfgname))
|
|
||||||
return NULL;
|
|
||||||
baudrate = (ibaud << 16) | obaud;
|
|
||||||
err = is_setconfig(baudrate, (long)flags, idrvname, odrvname, cfgname);
|
|
||||||
if ( err ) {
|
|
||||||
PyErr_Mac(ErrorObject, err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Py_INCREF(Py_None);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* List of methods defined in the module */
|
|
||||||
|
|
||||||
static struct PyMethodDef pyis_methods[] = {
|
|
||||||
{"open", pyis_open, 1, pyis_open__doc__},
|
|
||||||
{"connect", pyis_connect, 1, pyis_connect__doc__},
|
|
||||||
{"disconnect", pyis_disconnect, 1, pyis_disconnect__doc__},
|
|
||||||
{"status", pyis_status, 1, pyis_status__doc__},
|
|
||||||
{"getconfig", pyis_getconfig, 1, pyis_getconfig__doc__},
|
|
||||||
{"setconfig", pyis_setconfig, 1, pyis_setconfig__doc__},
|
|
||||||
|
|
||||||
{NULL, NULL} /* sentinel */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialization function for the module (*must* be called initinterslip) */
|
|
||||||
|
|
||||||
static char interslip_module_documentation[] =
|
|
||||||
""
|
|
||||||
;
|
|
||||||
|
|
||||||
void
|
|
||||||
initinterslip()
|
|
||||||
{
|
|
||||||
PyObject *m, *d;
|
|
||||||
|
|
||||||
/* Create the module and add the functions */
|
|
||||||
m = Py_InitModule4("interslip", pyis_methods,
|
|
||||||
interslip_module_documentation,
|
|
||||||
(PyObject*)NULL,PYTHON_API_VERSION);
|
|
||||||
|
|
||||||
/* Add some symbolic constants to the module */
|
|
||||||
d = PyModule_GetDict(m);
|
|
||||||
ErrorObject = PyString_FromString("interslip.error");
|
|
||||||
PyDict_SetItemString(d, "error", ErrorObject);
|
|
||||||
|
|
||||||
/* XXXX Add constants here */
|
|
||||||
|
|
||||||
PyDict_SetItemString(d, "IDLE", PyInt_FromLong(IS_IDLE));
|
|
||||||
PyDict_SetItemString(d, "WMODEM", PyInt_FromLong(IS_WMODEM));
|
|
||||||
PyDict_SetItemString(d, "DIAL", PyInt_FromLong(IS_DIAL));
|
|
||||||
PyDict_SetItemString(d, "LOGIN", PyInt_FromLong(IS_LOGIN));
|
|
||||||
PyDict_SetItemString(d, "RUN", PyInt_FromLong(IS_RUN));
|
|
||||||
PyDict_SetItemString(d, "DISC", PyInt_FromLong(IS_DISC));
|
|
||||||
|
|
||||||
/* Check for errors */
|
|
||||||
if (PyErr_Occurred())
|
|
||||||
Py_FatalError("can't initialize module interslip");
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,484 +0,0 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
|
||||||
<HTML>
|
|
||||||
|
|
||||||
<HEAD>
|
|
||||||
|
|
||||||
<TITLE>HOWTO: Compiling Python Modules with MPW</TITLE>
|
|
||||||
|
|
||||||
</HEAD>
|
|
||||||
|
|
||||||
<BODY>
|
|
||||||
|
|
||||||
<H1>HOWTO: Compiling Python Modules with MPW</H1>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
This HOWTO is a slightly reformatted version of an original by
|
|
||||||
<A HREF="mailto:cwebster@nevada.edu">Corran Webster</A>, whose
|
|
||||||
<A HREF="http://www.nevada.edu/~cwebster/Python/">Python page</A>
|
|
||||||
may contain a more up-to-date version.
|
|
||||||
</blockquote>
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
The <A HREF="http://www.cwi.nl/~jack/macpython.html">Macintosh version</A>
|
|
||||||
of the <A HREF="http://www.python.org/">Python programming language</A> is
|
|
||||||
usually compiled with <A HREF="http://www.metrowerks.com/">Metrowerks
|
|
||||||
CodeWarrior</A>. As a result, C extension modules are also usually
|
|
||||||
compiled with CodeWarrior, and the documentation and sample code reflects
|
|
||||||
this. CodeWarrior is a commercial product, and may be beyond the budgets
|
|
||||||
of hobbyist hackers, making them dependent on others to compile C extension
|
|
||||||
modules. At the present time, many standard C extension modules compile
|
|
||||||
"out of the box" on the Macintosh, but in only a few cases is the plugin
|
|
||||||
for the Macintosh included in the distribution.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
The <A HREF="http://developer.apple.com/tools/mpw-tools/">Macintosh
|
|
||||||
Programmer's Workshop</A> (MPW) is Apple's development environment, and is
|
|
||||||
freely available for <A
|
|
||||||
HREF="ftp://ftp.apple.com/developer/Tool_Chest/Core_Mac_OS_Tools/MPW_etc./">download</A>
|
|
||||||
from Apple, as well as on their Developer CDs. Since Python was originally
|
|
||||||
developed using MPW, before CodeWarrior became the dominant MacOS
|
|
||||||
development environment, most of the idiosyncrasies of MPW are already
|
|
||||||
supported, and compilation of C extension modules in MPW is possible.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
This HOWTO only deals with compiling for PowerPC Macintoshes. The process
|
|
||||||
should be similar for 68k Macintoshes using the code fragment manager, but
|
|
||||||
I have not attempted this - my old Mac is running NetBSD.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
This way of compiling modules is still experimental. Please read the
|
|
||||||
caveats section below.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H2><A NAME="setup">Setting Up MPW for Compiling Python Modules</A></H2>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
This assumes that you have successfully installed both MPW and Python with
|
|
||||||
the Developer's Kit on your Macintosh.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
The first step is to let MPW know where you keep Python. This step is not
|
|
||||||
strictly necessary, but will make development easier and improve
|
|
||||||
portability. Create a new file in the <CODE>Startup Items</CODE> folder of
|
|
||||||
MPW called <A HREF="Python"><CODE>Python</CODE></A>. Type the lines:
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
set Python "Macintosh HD:Applications:Python 1.5.2c1:"
|
|
||||||
set PythonIncludes "{Python}Include"
|
|
||||||
set PythonMacIncludes "{Python}Mac:Include"
|
|
||||||
set PythonCore "{Python}PythonCore"
|
|
||||||
|
|
||||||
export Python PythonIncludes PythonMacIncludes PythonCore
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
where <CODE>Macintosh HD:Applications:Python 1.5.2c1:</CODE> is replaced by
|
|
||||||
the path to the directory where you keep your copy of Python, and the other
|
|
||||||
variables reflect where you keep your header files and Python core files.
|
|
||||||
The locations here are the standard for Python 1.5.2c1, but they are
|
|
||||||
different for Python 1.52b2 and earlier (most notably, the PythonCore is
|
|
||||||
kept in the Extensions folder).
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Next, you need to update the <A HREF="config.h"><CODE>config.h</CODE></A>
|
|
||||||
file for the <CODE>MrC</CODE> compiler included with MPW. This header file
|
|
||||||
is located in the <CODE>:Mac:Include</CODE> folder in the standard
|
|
||||||
distribution. You can update it by hand, by adding the lines:
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
#ifdef __MRC__
|
|
||||||
#define BAD_STATIC_FORWARD
|
|
||||||
#endif
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
at the after the similar defines for <CODE>__MWERKS__</CODE> and
|
|
||||||
<CODE>__SC__</CODE> in the file. This step is critical: many modules,
|
|
||||||
including ones in the standard distribution, will not compile properly
|
|
||||||
without this modification (see common problems below).
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Copies of both the <A HREF="Python"><CODE>Python</CODE></A> startup item
|
|
||||||
for MPW and the <A HREF="config.h"><CODE>config.h</CODE></A> are included
|
|
||||||
here for your convenience.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
If you are porting Unix modules to the mac, you may find it useful to
|
|
||||||
install <A
|
|
||||||
HREF="http://www.iis.ee.ethz.ch/~neeri/macintosh/gusi-qa.html">GUSI</A> for
|
|
||||||
your copy of MPW. GUSI provides some amount of POSIX compatibility, and is
|
|
||||||
used by Python itself for this purpose - at the very least having it's
|
|
||||||
header files available may be useful. Also of note for people porting Unix
|
|
||||||
modules, the most recent alpha version (4.1a8) of <CODE>MrC</CODE> and
|
|
||||||
<CODE>MrCpp</CODE> at this writing permits using unix-style pathnames for
|
|
||||||
includes via the <CODE>-includes unix</CODE> command line option. I have
|
|
||||||
not experimented heavily with this, but will be doing so in the future and
|
|
||||||
report my findings.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
You now have MPW and Python set up to allow compilation of modules.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H2><A NAME="compiling">Compiling a Module</A></H2>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
This assumes that you have a C extension module ready to compile. For
|
|
||||||
instructions on how to write a module, see the Python documentation.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
There are three approaches you can take to compiling in MPW: using the
|
|
||||||
command line interface, using the MPW <CODE>CreateMake</CODE> command
|
|
||||||
(available as the "Create build commands..." menu item, and writing a
|
|
||||||
Makefile by hand.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Before you start any of these, you'll need to know:
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
<LI>The names and locations of the C source files. In the examples, this
|
|
||||||
is the file <A HREF="xxmodule.c"><CODE>xxmodule.c</CODE></A>, and is in
|
|
||||||
MPW's current working directory.
|
|
||||||
<LI>The name that Python expects to import your module under. In the
|
|
||||||
examples, this is <CODE>xx</CODE>, so the shared library file will be
|
|
||||||
called <CODE>xx.ppc.slb</CODE>.
|
|
||||||
<LI>The location of any additional header files use by the C source. The
|
|
||||||
example does not use any additional header files.
|
|
||||||
<LI>The location of any additional shared libraries which the module needs
|
|
||||||
to link to. The example does not link to any other shared libraries.
|
|
||||||
<LI>The name of the entry point to your module. This is usually the last
|
|
||||||
function in the main C source file, and the name usually starts with
|
|
||||||
<CODE>init</CODE>. In the examples, this is <CODE>initxx</CODE>.
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<H3>Using the Command Line</H3>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
For simple modules consisting of one or two C files, it's often convenient
|
|
||||||
to simply use commands in a MPW Worksheet. Usually you will want to set
|
|
||||||
MPW's working directory to the directory containing the C source code. The
|
|
||||||
following commands compile and link the standard Python test module <A
|
|
||||||
HREF="xxmodule.c"><CODE>xxmodule.c</CODE></A>:
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
MrC "xxmodule.c" -o "xx.c.x" -w off -d HAVE_CONFIG_H ∂
|
|
||||||
-i "{PythonMacIncludes}" ∂
|
|
||||||
-i "{PythonIncludes}"
|
|
||||||
PPCLink ∂
|
|
||||||
-o "xx.ppc.slb" ∂
|
|
||||||
"xx.c.x" ∂
|
|
||||||
-t 'shlb' ∂
|
|
||||||
-c 'Pyth' ∂
|
|
||||||
-xm s ∂
|
|
||||||
-d ∂
|
|
||||||
"{PythonCore}" ∂
|
|
||||||
"{SharedLibraries}InterfaceLib" ∂
|
|
||||||
"{SharedLibraries}MathLib" ∂
|
|
||||||
"{SharedLibraries}StdCLib" ∂
|
|
||||||
"{PPCLibraries}StdCRuntime.o" ∂
|
|
||||||
"{PPCLibraries}PPCCRuntime.o" ∂
|
|
||||||
"{PPCLibraries}PPCToolLibs.o" ∂
|
|
||||||
-export initxx
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
(Note: The last character on each line should appear as "partial
|
|
||||||
derivative" symbol, which you type as <KBD>option-d</KBD> and which is
|
|
||||||
MPW's line continuation symbol.)
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Any additional header files should be specified by adding their directories
|
|
||||||
as extra <CODE>-i</CODE> options to the <CODE>MrC</CODE> command. Any
|
|
||||||
additional shared libraries should be added before the PythonCore library
|
|
||||||
in the <CODE>PPCLink</CODE> command.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
If there is more than one source file, you will need to duplicate the
|
|
||||||
compile command for each source file, and you will need to include all the
|
|
||||||
object files in the place where <CODE>"xx.c.x"</CODE> appears in the
|
|
||||||
<CODE>PPCLink</CODE> command.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H3>Using CreateMake</H3>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
For more complex modules, or modules that you are writing yourself, you
|
|
||||||
will probably want to use a makefile. Unfortunately MPW's makefiles are
|
|
||||||
incompatible with the standard Unix makefiles, so you will not be able to
|
|
||||||
use any makefiles which come with a C module.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Usually, you will want the makefile to reside in the same directory as the
|
|
||||||
C source code, so you should set MPW's working directory to that directory
|
|
||||||
before proceeding.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
To create a makefile for the standard Python test module <A
|
|
||||||
HREF="xxmodule.c"><CODE>xxmodule.c</CODE></A>:
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
<LI>Select "Create build commands..." from the "Build" Menu.
|
|
||||||
<LI>Type <KBD>xx.ppc.slb</KBD> for the Program Name.
|
|
||||||
<LI>Select "Shared Library" for the Program Type.
|
|
||||||
<LI>Select "PowerPC Only" for the Target.
|
|
||||||
<LI>Click on the "Source Files..." button, and add your module's C source
|
|
||||||
files to the list.
|
|
||||||
<LI>Click on the "Other Options..." button and change the creator type to
|
|
||||||
"Pyth". If you are using additional header files, you can also add their
|
|
||||||
directories at this stage. Click on "Continue" once you have done this.
|
|
||||||
<LI>Click on the "Exported Symbols..." button and type <KBD>initxx</KBD>
|
|
||||||
into the entry field. Click on "Continue" once you have done this.
|
|
||||||
<LI>At this stage, your CreateMake window should look like this: <IMG
|
|
||||||
SRC="html.icons/createmake.png" ALT="[picture of commando window for CreateMake]">
|
|
||||||
<LI>Click on the "CreateMake" button.
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
You will now need to edit the makefile that was just created. Open the
|
|
||||||
file "xx.ppc.slb.make" in the current directory and make the following
|
|
||||||
changes:
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
<LI>Change the line
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
Includes =
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
to read
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
Includes = -i "{PythonIncludes}" -i "{PythonMacIncludes}"
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
If you have any additional headers than need to be included, you can add
|
|
||||||
them here as well.
|
|
||||||
<LI>Change the line
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
PPCCOptions = {Includes} {Sym•PPC}
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
to read
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
PPCCOptions = -w off -d HAVE_CONFIG_H {Includes} {Sym•PPC}
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<LI>After the line
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
-xm s ∂
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
add
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
-d ∂
|
|
||||||
"{PythonCore}" ∂
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
If you have any other shared libraries you need to link to, add each on a
|
|
||||||
line before PythonCore, terminating each line with a <CODE>∂</CODE>.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<P>Save the file. You are now ready to build.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Go to the "Build" or "Full Build" menu items, type in
|
|
||||||
<KBD>xx.ppc.slb</KBD>, and MPW should take things from there. Any time you
|
|
||||||
need to rebuild the shared library, you can simply do another "Build" or
|
|
||||||
"Full Build".
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H3>Writing a Makefile by Hand</H3>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
For modules which have complex interdependencies between files, you will
|
|
||||||
likely need a more sophisticated makefile than the one created by
|
|
||||||
<CODE>CreateMake</CODE>. You will need to be familiar with the MPW
|
|
||||||
makefile format, but you can get a start by either using
|
|
||||||
<CODE>CreateMake</CODE> to get a simple starting point, or taking another
|
|
||||||
MPW makefile as a starting point.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
It is beyond the scope of this HOWTO to go into the generalities of MPW
|
|
||||||
makefiles. Documentation on MPW's <CODE>Make</CODE> command can be found
|
|
||||||
with the MPW distribution, in particular the documents <A
|
|
||||||
HREF="http://developer.apple.com/tools/mpw-tools/books.html#Building">Building
|
|
||||||
and Maintaining Programs with MPW (2nd Edition)</A> and the <A
|
|
||||||
HREF="http://developer.apple.com/tools/mpw-tools/books.html#CommandRef">MPW
|
|
||||||
Command Reference</A>.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
There are a couple of important points to keep in mind when writing a
|
|
||||||
makefile by hand:</P>
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
<LI>When there are multiple symbols with the same name in object files or
|
|
||||||
shared libraries, <CODE>PPCLink</CODE> used the symbol from the file which
|
|
||||||
appears first in arguments of the <CODE>PPCLink</CODE> command. For this
|
|
||||||
reason, you will usually want the PythonCore and any other shared libraries
|
|
||||||
which are not part of the standard MPW runtime environment to appear before
|
|
||||||
the standard runtime libraries. This is particularly the case with
|
|
||||||
StdCLib. The "-d" option turns off the (often copious) warnings about
|
|
||||||
multiply defined symbols.
|
|
||||||
<LI>You will want to make sure that the <CODE>HAVE_CONFIG_H</CODE>
|
|
||||||
preprocessor symbol is defined for most C source files using the <CODE>-d
|
|
||||||
HAVE_CONFIG_H</CODE> option to <CODE>MrC</CODE>.
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
The file <A HREF="xx.ppc.slb.make.sit.hqx"><CODE>xx.ppc.slb.make</CODE></A>
|
|
||||||
is included here for you to use as a starting point.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H2><A NAME="using">Using the Extension Module</A></H2>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Once you have compiled your extension module, you will need to let Python
|
|
||||||
know where it is. You can either move it into a place on Python's search
|
|
||||||
path - such as the <CODE>:Mac:Plugins</CODE> folder - or modify the path to
|
|
||||||
include the location of your new module using the
|
|
||||||
<CODE>EditPythonPrefs</CODE> applet.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Your work may not be completely done, as many extension modules have a
|
|
||||||
Python wrapper around them. If the Python was not written with portability
|
|
||||||
in mind, you may need to do some more work to get that up and running.
|
|
||||||
Indeed, if the Python part uses OS-specific features, like pipes, you may
|
|
||||||
have to completely rewrite it if you can make it work at all.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H2><A NAME="problems">Common Problems</A></H2>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
There are a couple of common problems which occur when porting a module
|
|
||||||
from another platform. Fortunately, they are often easy to fix.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H3>Static Forward Definitions</H3>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
If you get a compiler error which looks something like:
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<PRE>
|
|
||||||
File "xxmodule.c"; line 135 #Error: 'Xxo_Type' is already defined
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
then most likely either you have not set up <CODE>config.h</CODE> correctly
|
|
||||||
to handle static forward definitions, or the module author has not adhered
|
|
||||||
to the standard python conventions. If the second is the case, find where
|
|
||||||
the variable is first defined, and replace the <CODE>static</CODE> with
|
|
||||||
<CODE>staticforward</CODE>. Then find the second place it is defined
|
|
||||||
(usually the line where the compiler complained) and replace
|
|
||||||
<CODE>static</CODE> with <CODE>statichere</CODE>.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
If you have set up things correctly, you should now be able to compile.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H3>Automatic Type Conversion</H3>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<CODE>MrC</CODE> seems to be a little pickier about automatically
|
|
||||||
converting from one type to another than some other C compilers. These can
|
|
||||||
often be fixed by simply adding an explicit cast to the desired type.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
XXX There may be a compiler option which relaxes this. That would be a
|
|
||||||
better solution.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H2><A NAME="caveats">Caveats</A></H2>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
As Jack Jansen pointed out on the Mac Python mailing list, there could
|
|
||||||
potentially be conflicts between the MetroWerks C runtime which the Python
|
|
||||||
core and standard modules was compiled with, and the MPW C runtime which
|
|
||||||
your extension module is compiled with. While things seem to work fine in
|
|
||||||
everyday use, it is possible that there are bugs which have not been
|
|
||||||
discovered yet. Most likely these world take the form of standard C
|
|
||||||
functions (most likely I/O functions due to conflicts between the SIOUX
|
|
||||||
libraries and the SIOW libraries) not working as they are supposed to, or
|
|
||||||
memory leaks caused by improper malloc/free.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Some such problems have been demonstrated by compiling modules with
|
|
||||||
PythonCore linked after StdCLib - printf does not work properly in this
|
|
||||||
setup, and I suspect that there will also be malloc/free problems in
|
|
||||||
situations where the module allocates memory which is later disposed of by
|
|
||||||
Python, or vice-versa. Compiling with PythonCore taking precedence over
|
|
||||||
StdCLib seems to give the correct behaviour.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
This method of compiling should be considered experimental for the time
|
|
||||||
being. <STRONG>Use it at your own risk.</STRONG>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
If you notice any quirks in modules compiled this way, or have insight into
|
|
||||||
what may go wrong or right with this situation, <A
|
|
||||||
HREF="mailto:cwebster@nevada.edu">please contact me</A> so that I can add
|
|
||||||
it to the HOWTO.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
The ideal solution to this problem would be to get Python to compile using
|
|
||||||
MPW (and a Python MPW Tool would be very neat indeed). However, that does
|
|
||||||
seem to be a major project.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<DIV class=footer>
|
|
||||||
<HR>
|
|
||||||
<BR>
|
|
||||||
©<A HREF="mailto:cwebster@nevada.edu">Corran Webster</A>, 1999. <BR>
|
|
||||||
<!-- #LASTMODIFIED TEXT="Last modified" FORM="SHORT,TIME" -->
|
|
||||||
Last modified 14/12/99 12:17 PM
|
|
||||||
<!-- /#LASTMODIFIED -->
|
|
||||||
</DIV>
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
|
|
||||||
</HTML>
|
|
|
@ -1,324 +0,0 @@
|
||||||
<HTML><HEAD><TITLE>Creating a C extension module on the Macintosh</TITLE></HEAD>
|
|
||||||
<BODY>
|
|
||||||
<H1>Creating a C extension module on the Macintosh</H1>
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
This document gives a step-by-step example of how to create a new C
|
|
||||||
extension module on the mac. For this example, we will create a module
|
|
||||||
to interface to the programmers' API of InterSLIP, a package that
|
|
||||||
allows you to use MacTCP (and, hence, all internet services) over a
|
|
||||||
modem connection. The actual example does not work anymore, as both
|
|
||||||
MacTCP and Interslip died long ago, but the text is still mostly
|
|
||||||
correct.<p>
|
|
||||||
|
|
||||||
<H2>Prerequisites</H2>
|
|
||||||
|
|
||||||
There are a few things you need to pull this off. First and foremost,
|
|
||||||
you need a C development environment. Actually, you need a specific
|
|
||||||
development environment, CodeWarrior by <A
|
|
||||||
HREF="http://www.metrowerks.com/">MetroWerks</A>. You will
|
|
||||||
need Version 7 or later. You may be able to get by with an older
|
|
||||||
version of CodeWarrior or with another development environment (Up to
|
|
||||||
about 1994 python was developed with THINK C, and in the dim past it
|
|
||||||
was compiled with MPW C) assuming you have managed to get Python to
|
|
||||||
compile under your development environment, but the step-by-step
|
|
||||||
character of this document will be lost. <p>
|
|
||||||
|
|
||||||
Next, you need to install the Developer option in the MacPython installer.
|
|
||||||
You may also find that Guido's <A
|
|
||||||
HREF="http://www.python.org/doc/ext/ext.html">Extending and embedding
|
|
||||||
the Python interpreter</A> is a very handy piece of documentation. I
|
|
||||||
will skip lots of details that are handled there, like complete
|
|
||||||
descriptions of <CODE>Py_ParseTuple</CODE> and such utility routines, or
|
|
||||||
the general structure of extension modules. <p>
|
|
||||||
|
|
||||||
<H2>InterSLIP and the C API to it</H2>
|
|
||||||
|
|
||||||
InterSLIP, the utility to which we are going to create a python
|
|
||||||
interface, is a system extension that does all the work of connecting
|
|
||||||
to the internet over a modem connection. InterSLIP is provided
|
|
||||||
free-of-charge by <A
|
|
||||||
HREF="http://www.intercon.com/">InterCon</A>. First it connects to
|
|
||||||
your modem, then it goes through the whole process of dialling,
|
|
||||||
logging in and possibly starting the SLIP software on the remote
|
|
||||||
computer and finally it starts with the real work: packing up IP
|
|
||||||
packets handed to it by MacTCP and sending them to the remote side
|
|
||||||
(and, of course, the reverse action of receiving incoming packets,
|
|
||||||
unpacking them and handing them to MacTCP). InterSLIP is a device
|
|
||||||
driver, and you control it using a application supplied with it,
|
|
||||||
InterSLIP Setup. The API that InterSLIP Setup uses to talk to the
|
|
||||||
device driver is published in the documentation and, hence, also
|
|
||||||
useable by other applications. <p>
|
|
||||||
|
|
||||||
I happened to have a C interface to the API, which is all ugly
|
|
||||||
low-level device-driver calls by itself. The C interface is in <A
|
|
||||||
HREF="interslip/InterslipLib.c">InterslipLib.c</A> and <A
|
|
||||||
HREF="interslip/InterslipLib.h">InterslipLib.h</A>, we'll
|
|
||||||
concentrate here on how to build the Python wrapper module around
|
|
||||||
it. Note that this is the "normal" situation when you are writing a
|
|
||||||
Python extension module: you have some sort of functionality available
|
|
||||||
to C programmers and want to make a Python interface to it. <p>
|
|
||||||
|
|
||||||
<H2>Using Modulator</H2>
|
|
||||||
|
|
||||||
The method we describe in this document, using Modulator, is the best
|
|
||||||
method for small interfaces. For large interfaces there is another
|
|
||||||
tool, Bgen, which actually generates the complete module without you
|
|
||||||
lifting a single finger. Bgen, however, has the disadvantage of having
|
|
||||||
a very steep learning curve, so an example using it will have to wait
|
|
||||||
until another document, when I have more time. <p>
|
|
||||||
|
|
||||||
First, let us look at the <A
|
|
||||||
HREF="interslip/InterslipLib.h">InterslipLib.h</A> header file,
|
|
||||||
and see that the whole interface consists of six routines:
|
|
||||||
<CODE>is_open</CODE>, <CODE>is_connect</CODE>,
|
|
||||||
<CODE>is_disconnect</CODE>, <CODE>is_status</CODE>,
|
|
||||||
<CODE>is_getconfig</CODE> and <CODE>is_setconfig</CODE>. Our first
|
|
||||||
step will be to create a skeleton file <A
|
|
||||||
HREF="interslip/@interslipmodule.c">@interslipmodule.c</A>, a
|
|
||||||
dummy module that will contain all the glue code that python expects
|
|
||||||
of an extension module. Creating this glue code is a breeze with
|
|
||||||
modulator, a tool that we only have to tell that we want to create a
|
|
||||||
module with methods of the six names above and that will create the
|
|
||||||
complete skeleton C code for us. <p>
|
|
||||||
|
|
||||||
Why call this dummy module <CODE>@interslipmodule.c</CODE> and not
|
|
||||||
<CODE>interslipmodule.c</CODE>? Self-preservation: if ever you happen
|
|
||||||
to repeat the whole process after you have actually turned the
|
|
||||||
skeleton module into a real module you would overwrite your
|
|
||||||
hand-written code. By calling the dummy module a different name you
|
|
||||||
have to make <EM>two</EM> mistakes in a row before you do this. <p>
|
|
||||||
|
|
||||||
If you installed Tk support when you installed Python this is extremely
|
|
||||||
simple. You start modulator and are provided with a form in which you
|
|
||||||
fill out the details of the module you are creating. <p>
|
|
||||||
|
|
||||||
<IMG SRC="html.icons/modulator.gif" ALIGN=CENTER><p>
|
|
||||||
|
|
||||||
You'll need to supply a module name (<CODE>interslip</CODE>, in our
|
|
||||||
case), a module abbreviation (<CODE>pyis</CODE>, which is used as a
|
|
||||||
prefix to all the routines and data structures modulator will create
|
|
||||||
for you) and you enter the names of all the methods your module will
|
|
||||||
export (the list above, with <CODE>is_</CODE> stripped off). Note that
|
|
||||||
we use <CODE>pyis</CODE> as the prefix instead of the more logical
|
|
||||||
<CODE>is</CODE>, since the latter would cause our routine names to
|
|
||||||
collide with those in the API we are interfacing to! The method names
|
|
||||||
are the names as seen by the python program, and the C routine names
|
|
||||||
will have the prefix and an underscore prepended. Modulator can do
|
|
||||||
much more, like generating code for objects and such, but that is a
|
|
||||||
topic for a later example. <p>
|
|
||||||
|
|
||||||
Once you have told modulator all about the module you want to create
|
|
||||||
you press "check", which checks that you haven't omitted any
|
|
||||||
information and "Generate code". This will prompt you for a C output
|
|
||||||
file and generate your module for you. <p>
|
|
||||||
|
|
||||||
<H2>Using Modulator without Tk</H2>
|
|
||||||
|
|
||||||
|
|
||||||
Modulator actually uses a two-stage process to create your code: first
|
|
||||||
the information you provided is turned into a number of python
|
|
||||||
statements and then these statements are executed to generate your
|
|
||||||
code. This is done so that you can even use modulator if you don't
|
|
||||||
have Tk support in Python: you'll just have to write the modulator
|
|
||||||
python statements by hand (about 10 lines, in our example) and
|
|
||||||
modulator will generate the C code (about 150 lines, in our
|
|
||||||
example). Here is the Python code you'll want to execute to generate
|
|
||||||
our skeleton module: <p>
|
|
||||||
|
|
||||||
<CODE><PRE>
|
|
||||||
import addpack
|
|
||||||
addpack.addpack('Tools')
|
|
||||||
addpack.addpack('modulator')
|
|
||||||
import genmodule
|
|
||||||
|
|
||||||
m = genmodule.module()
|
|
||||||
m.name = 'interslip'
|
|
||||||
m.abbrev = 'pyis'
|
|
||||||
m.methodlist = ['open', 'connect', 'disconnect', 'status', \
|
|
||||||
'getconfig', 'setconfig']
|
|
||||||
m.objects = []
|
|
||||||
|
|
||||||
fp = open('@interslipmodule.c', 'w')
|
|
||||||
genmodule.write(fp, m)
|
|
||||||
</PRE></CODE>
|
|
||||||
|
|
||||||
Drop this program on the python interpreter and out will come your
|
|
||||||
skeleton module. <p>
|
|
||||||
|
|
||||||
Now, rename the file to interslipmodule.c and you're all set to start
|
|
||||||
developing. The module is complete in the sense that it should
|
|
||||||
compile, and that if you import it in a python program you will see
|
|
||||||
all the methods. It is, of course, not yet complete in a functional
|
|
||||||
way... <p>
|
|
||||||
|
|
||||||
<H2>Creating a plugin module</H2>
|
|
||||||
|
|
||||||
The easiest way to build a plugin module is to use the distutils package,
|
|
||||||
this works fine on MacOS with CodeWarrior. See the distutils documentation
|
|
||||||
for details. Keep in mind that even though you are on the Mac you specify
|
|
||||||
filenames with Unix syntax: they are actually URLs, not filenames.
|
|
||||||
<p>
|
|
||||||
|
|
||||||
Alternatively you can build the project file by hand.
|
|
||||||
Go to the ":Mac:Build" folder and copy the files xx.carbon.mcp,
|
|
||||||
and xx.carbon.mcp.exp to interslipmodule.carbon.mcp and
|
|
||||||
interslipmodule.carbon.mcp.exp, respectively. Edit
|
|
||||||
interslipmodule.carbon.mcp.exp and change the name of the exported routine
|
|
||||||
"initxx" to "initinterslip". Open interslipmodule.carbon.mcp with CodeWarrior,
|
|
||||||
remove the file xxmodule.c and add interslipmodule.c and make a number
|
|
||||||
of adjustments to the preferences:
|
|
||||||
<UL>
|
|
||||||
<LI> in PPC target, set the output file name to "interslipmodule.carbon.slb",
|
|
||||||
<LI> if you are working without a source distribution (i.e. with a normal
|
|
||||||
binary distribution plus a development distribution) you will not have
|
|
||||||
a file <code>PythonCoreCarbon</code>. The installation process has deposited this
|
|
||||||
file in the System <code>Extensions</code> folder under the name
|
|
||||||
<code>PythonCoreCarbon <i>version</i></code>. Add that file to the project, replacing
|
|
||||||
<code>PythonCoreCarbon</code>.
|
|
||||||
<LI> you must either download and build GUSI (if your extension module uses sockets
|
|
||||||
or other Unix I/O constructs) or remove GUSI references from the Access Paths
|
|
||||||
settings. See the <a href="building.html">Building</a> document for where to get GUSI
|
|
||||||
and how to build it.
|
|
||||||
</UL>
|
|
||||||
Next, compile and link your module, fire up python and test it. <p>
|
|
||||||
|
|
||||||
<H2>Getting the module to do real work</H2>
|
|
||||||
|
|
||||||
So far, so good. In half an hour or so we have created a complete new
|
|
||||||
extension module for Python. The downside, however, is that the module
|
|
||||||
does not do anything useful. So, in the next half hour we will turn
|
|
||||||
our beautiful skeleton module into something that is at least as
|
|
||||||
beautiful but also gets some serious work done. For this once,
|
|
||||||
<EM>I</EM> have spent that half hour for you, and you can see the
|
|
||||||
results in <A
|
|
||||||
HREF="interslip/interslipmodule.c">interslipmodule.c</A>. <p>
|
|
||||||
|
|
||||||
We add
|
|
||||||
<CODE><PRE>
|
|
||||||
#include "InterslipLib.h"
|
|
||||||
#include "macglue.h"
|
|
||||||
</PRE></CODE>
|
|
||||||
to the top of the file, and work our way through each of the methods
|
|
||||||
to add the functionality needed. Starting with open, we fill in the
|
|
||||||
template docstring, the value accessible from Python by looking at
|
|
||||||
<CODE>interslip.open.__doc__</CODE>. There are not many tools using
|
|
||||||
this information at the moment, but as soon as class browsers for
|
|
||||||
python become available having this minimal documentation available is
|
|
||||||
a good idea. We put "Load the interslip driver" as the comment
|
|
||||||
here. <p>
|
|
||||||
|
|
||||||
Next, we tackle the body of <CODE>pyis_open()</CODE>. Since it has no
|
|
||||||
arguments and no return value we don't need to mess with that, we just
|
|
||||||
have to add a call to <CODE>is_open()</CODE> and check the return for
|
|
||||||
an error code, in which case we raise an error:
|
|
||||||
<CODE><PRE>
|
|
||||||
err = is_open();
|
|
||||||
if ( err ) {
|
|
||||||
PyErr_Mac(ErrorObject, err);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
</PRE></CODE>
|
|
||||||
The routine <CODE><A NAME="PyErr_Mac">PyErr_Mac()</A></CODE> is a
|
|
||||||
useful routine that raises the exception passed as its first
|
|
||||||
argument. The data passed with the exception is based on the standard
|
|
||||||
MacOS error code given, and PyErr_Mac() attempts to locate a textual
|
|
||||||
description of the error code (which sure beats the "error -14021"
|
|
||||||
messages that so many macintosh applications tell their poor
|
|
||||||
users). <p>
|
|
||||||
|
|
||||||
We will skip pyis_connect and pyis_disconnect here, which are pretty
|
|
||||||
much identical to pyis_open: no arguments, no return value, just a
|
|
||||||
call and an error check. With pyis_status() things get interesting
|
|
||||||
again: this call still takes 3 arguments, and all happen to be values
|
|
||||||
returned (a numeric connection status indicator, a message sequence
|
|
||||||
number and a pointer to the message itself, in MacOS pascal-style
|
|
||||||
string form). We declare variables to receive the returned values, do
|
|
||||||
the call, check the error and format the return value. <p>
|
|
||||||
|
|
||||||
Building the return value is done using <CODE><A
|
|
||||||
NAME="Py_BuildValue">Py_BuildValue</A></CODE>:
|
|
||||||
<CODE><PRE>
|
|
||||||
return Py_BuildValue("iiO&", (int)status, (int)seqnum, PyMac_BuildStr255, message);
|
|
||||||
</PRE></CODE>
|
|
||||||
Py_BuildValue() is a very handy routine that builds tuples according
|
|
||||||
to a format string, somewhat similar to the way <CODE>printf()</CODE>
|
|
||||||
works. The format string specifies the arguments expected after the
|
|
||||||
string, and turns them from C objects into python objects. The
|
|
||||||
resulting objects are put in a python tuple object and returned. The
|
|
||||||
"i" format specifier signifies an "int" (hence the cast: status and
|
|
||||||
seqnum are declared as "long", which is what the is_status() routine
|
|
||||||
wants, and even though we use a 4-byte project there is really no
|
|
||||||
reason not to put the cast here). Py_BuildValue and its counterpart
|
|
||||||
Py_ParseTuple have format codes for all the common C types like ints,
|
|
||||||
shorts, C-strings, floats, etc. Also, there is a nifty escape
|
|
||||||
mechanism to format values about which is does not know. This is
|
|
||||||
invoked by the "O&" format: it expects two arguments, a routine
|
|
||||||
pointer and an int-sized data object. The routine is called with the
|
|
||||||
object as a parameter and it should return a python objects
|
|
||||||
representing the data. <CODE>Macglue.h</CODE> declares a number of
|
|
||||||
such formatting routines for common MacOS objects like Str255, FSSpec,
|
|
||||||
OSType, Rect, etc. See the comments in the include file for
|
|
||||||
details. <p>
|
|
||||||
|
|
||||||
<CODE>Pyis_getconfig()</CODE> is again similar to pyis_getstatus, only
|
|
||||||
two minor points are worth noting here. First, the C API return the
|
|
||||||
input and output baudrate squashed together into a single 4-byte
|
|
||||||
long. We separate them out before returning the result to
|
|
||||||
python. Second, whereas the status call returned us a pointer to a
|
|
||||||
<CODE>Str255</CODE> it kept we are responsible for allocating the
|
|
||||||
<CODE>Str255</CODE> for getconfig. This is something that would have
|
|
||||||
been easy to get wrong had we not used prototypes everywhere. Morale:
|
|
||||||
always try to include the header files for interfaces to libraries and
|
|
||||||
other stuff, so that the compiler can catch any mistakes you make. <p>
|
|
||||||
|
|
||||||
<CODE>Pyis_setconfig()</CODE> finally shows off
|
|
||||||
<CODE>Py_ParseTuple</CODE>, the companion function to
|
|
||||||
<CODE>Py_BuildValue</CODE>. You pass it the argument tuple "args"
|
|
||||||
that your method gets as its second argument, a format string and
|
|
||||||
pointers to where you want the arguments stored. Again, standard C
|
|
||||||
types such as strings and integers Py_ParseTuple knows all about and
|
|
||||||
through the "O&" format you can extend the functionality. For each
|
|
||||||
"O&" you pass a function pointer and a pointer to a data area. The
|
|
||||||
function will be called with a PyObject pointer and your data pointer
|
|
||||||
and it should convert the python object to the correct C type. It
|
|
||||||
should return 1 on success and 0 on failure. Again, a number of
|
|
||||||
converters for standard MacOS types are provided, and declared in
|
|
||||||
<CODE>macglue.h</CODE>. <p>
|
|
||||||
|
|
||||||
Next in our source file comes the method table for our module, which
|
|
||||||
has been generated by modulator (and it did a good job too!), but
|
|
||||||
which is worth looking at for a moment. Entries are of the form
|
|
||||||
<CODE><PRE>
|
|
||||||
{"open", pyis_open, 1, pyis_open__doc__},
|
|
||||||
</PRE></CODE>
|
|
||||||
where the entries are python method name, C routine pointer, flags and
|
|
||||||
docstring pointer. The value to note is the 1 for the flags: this
|
|
||||||
signifies that you want to use "new-style" Py_ParseTuple behaviour. If
|
|
||||||
you are writing a new module always use this, but if you are modifying
|
|
||||||
old code which calls something like <CODE>getargs(args, "(ii)",
|
|
||||||
...)</CODE> you will have to put zero here. See "extending and
|
|
||||||
embedding" or possibly the getargs.c source file for details if you
|
|
||||||
need them. <p>
|
|
||||||
|
|
||||||
Finally, we add some code to the init module, to put some symbolic
|
|
||||||
constants (codes that can by returned by the status method) in the
|
|
||||||
module dictionary, so the python program can use "interslip.RUN"
|
|
||||||
instead of the cryptic "4" when it wants to check that the interslip
|
|
||||||
driver is in RUN state. Modulator has already generated code to get at
|
|
||||||
the module dictionary using PyModule_GetDict() to store the exception
|
|
||||||
object, so we simply call
|
|
||||||
<CODE><PRE>
|
|
||||||
PyDict_SetItemString(d, "IDLE", PyInt_FromLong(IS_IDLE));
|
|
||||||
</PRE></CODE>
|
|
||||||
for each of our items. Since the last bit of code in our init routine
|
|
||||||
checks for previous errors with <CODE>PyErr_Occurred()</CODE> and
|
|
||||||
since <CODE>PyDict_SetItemString()</CODE> gracefully handles the case
|
|
||||||
of <CODE>NULL</CODE> parameters (if <CODE>PyInt_FromLong()</CODE>
|
|
||||||
failed, for instance) we don't have to do error checking here. In some
|
|
||||||
other cases you may have to do error checking yourself. <p>
|
|
||||||
|
|
||||||
This concludes our crash-course on writing Python extensions in C on
|
|
||||||
the Macintosh. If you are not done reading yet I suggest you look
|
|
||||||
back at the <A HREF="index.html">MacPython Crashcourse index</A> to
|
|
||||||
find another topic to study. <p>
|
|
|
@ -1,93 +0,0 @@
|
||||||
import Printing
|
|
||||||
from Carbon import Qd
|
|
||||||
from Carbon import Fm
|
|
||||||
from Carbon import Res
|
|
||||||
|
|
||||||
# some constants
|
|
||||||
PostScriptBegin = 190 # Set driver state to PostScript
|
|
||||||
PostScriptEnd = 191 # Restore QuickDraw state
|
|
||||||
PostScriptHandle = 192 # PostScript data referenced in handle
|
|
||||||
|
|
||||||
CHUNK_SIZE = 0x8000 # max size of PicComment
|
|
||||||
|
|
||||||
def PostScript(text):
|
|
||||||
"""embed text as plain PostScript in print job."""
|
|
||||||
handle = Res.Resource('')
|
|
||||||
Qd.PicComment(PostScriptBegin, 0, handle)
|
|
||||||
while text:
|
|
||||||
chunk = text[:CHUNK_SIZE]
|
|
||||||
text = text[CHUNK_SIZE:]
|
|
||||||
handle.data = chunk
|
|
||||||
Qd.PicComment(PostScriptHandle, len(chunk), handle)
|
|
||||||
handle.data = ''
|
|
||||||
Qd.PicComment(PostScriptEnd, 0, handle)
|
|
||||||
|
|
||||||
# create a new print record
|
|
||||||
printrecord = Printing.NewTPrintRecord()
|
|
||||||
|
|
||||||
# open the printer
|
|
||||||
Printing.PrOpen()
|
|
||||||
try:
|
|
||||||
# initialize print record with default values
|
|
||||||
Printing.PrintDefault(printrecord)
|
|
||||||
|
|
||||||
# page setup, ok is 0 when user cancelled
|
|
||||||
ok = Printing.PrStlDialog(printrecord)
|
|
||||||
if not ok:
|
|
||||||
raise KeyboardInterrupt
|
|
||||||
# at this stage, you should save the print record in your document for later
|
|
||||||
# reference.
|
|
||||||
|
|
||||||
# print job dialog, ok is 0 when user cancelled
|
|
||||||
ok = Printing.PrJobDialog(printrecord)
|
|
||||||
if not ok:
|
|
||||||
raise KeyboardInterrupt
|
|
||||||
|
|
||||||
# once per document
|
|
||||||
port = Printing.PrOpenDoc(printrecord)
|
|
||||||
# port is the Printer's GrafPort, it is also the current port, so no need to Qd.SetPort(port)
|
|
||||||
try:
|
|
||||||
# start printing a page
|
|
||||||
# XXX should really look up what pages to print by
|
|
||||||
# inspecting the print record.
|
|
||||||
Printing.PrOpenPage(port, None)
|
|
||||||
try:
|
|
||||||
# use QuickDraw like in any other GrafPort
|
|
||||||
Qd.FrameRect((10, 250, 100, 500))
|
|
||||||
Qd.FrameRect((10, 510, 100, 600))
|
|
||||||
Qd.MoveTo(10, 100)
|
|
||||||
Qd.TextSize(50)
|
|
||||||
Qd.TextFont(Fm.GetFNum("Helvetica"))
|
|
||||||
Qd.DrawString("It rreally works!")
|
|
||||||
Qd.MoveTo(10, 150)
|
|
||||||
Qd.TextSize(20)
|
|
||||||
Qd.DrawString("(and now for a little PostScript...)")
|
|
||||||
|
|
||||||
# example PostScript code
|
|
||||||
ps = """
|
|
||||||
% the coordinate system is the quickdraw one, which is flipped
|
|
||||||
% compared to the default PS one. That means text will appear
|
|
||||||
% flipped when used directly from PostScript.
|
|
||||||
% As an example we start by defining a custom scalefont operator
|
|
||||||
% that corrects this.
|
|
||||||
/myscalefont{[exch 0 0 2 index neg 0 0]makefont}def
|
|
||||||
0.75 setgray
|
|
||||||
0 0 moveto
|
|
||||||
0 30 lineto 10000 30 lineto
|
|
||||||
10000 0 lineto closepath fill
|
|
||||||
0 setgray
|
|
||||||
5 25 moveto /Courier findfont 20 myscalefont setfont
|
|
||||||
(Printed with PostScript!) show
|
|
||||||
2 setlinewidth [10 10 5 10] 0 setdash 5 5 moveto 400 0 rlineto stroke
|
|
||||||
"""
|
|
||||||
# embed the PostScript code in the print job
|
|
||||||
PostScript(ps)
|
|
||||||
finally:
|
|
||||||
# when done with the page
|
|
||||||
Printing.PrClosePage(port)
|
|
||||||
finally:
|
|
||||||
# when done with the document
|
|
||||||
Printing.PrCloseDoc(port)
|
|
||||||
finally:
|
|
||||||
# when done printing
|
|
||||||
Printing.PrClose()
|
|
|
@ -1,429 +0,0 @@
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<TITLE>Using Python 2.0 on the Macintosh</TITLE>
|
|
||||||
</HEAD>
|
|
||||||
<BODY>
|
|
||||||
<H1>Using Python 2.0 on the Macintosh</H1>
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
This document is an introduction to using Python on the Apple
|
|
||||||
Macintosh. It does not introduce the language itself, for this you
|
|
||||||
should refer to the <A
|
|
||||||
HREF="http://www.python.org/doc/tut/tut.html">Python Tutorial</A> by
|
|
||||||
Guido van Rossum. This guide more-or-less replaces chapter two of the
|
|
||||||
tutorial, and provides some additional material. <p>
|
|
||||||
|
|
||||||
The tutorial, along with other indispensible documentation like the
|
|
||||||
library reference and such, is also available in a number of different
|
|
||||||
formats at <a href="http://www.python.org">
|
|
||||||
www.python.org</a>. The Adobe Acrobat <code>.pdf</code>
|
|
||||||
files are probably a good choice for reading or printing the documents
|
|
||||||
from your mac. <p>
|
|
||||||
|
|
||||||
There is currently no good tutorial for the mac-specific features of
|
|
||||||
Python, but to whet your appetite: it has interfaces to many MacOS
|
|
||||||
toolboxes (quickdraw, sound, quicktime, open scripting, etc) and
|
|
||||||
various portable toolboxes are available too (Tk, complex
|
|
||||||
numbers, image manipulation, etc). Some <A HREF="index.html">
|
|
||||||
annotated sample programs</A> are available to give you an idea of
|
|
||||||
Python's power. <P>
|
|
||||||
|
|
||||||
<h2>Using Python</h2>
|
|
||||||
|
|
||||||
The best way to start using Python is by using the <code>Python IDE</code>,
|
|
||||||
an integrated development environment with editor, debugger, class browser, etc.
|
|
||||||
Unfortunately the IDE is not yet documented here. Fortunately, however, it does not
|
|
||||||
need much documentation, so your best bet is to try it. <p>
|
|
||||||
|
|
||||||
<h2>Invoking the bare interpreter</h2>
|
|
||||||
|
|
||||||
An alternative method to use Python (and the method this document unfortunately emphasizes,
|
|
||||||
see the comment above) is to use the bare interpreter and an external text editor.
|
|
||||||
The name of the interpreter is <CODE>PythonInterpreter</CODE> and it is
|
|
||||||
recognizable by the "16 ton" icon. You start the
|
|
||||||
interpreter in interactive mode by double-clicking its icon: <p>
|
|
||||||
|
|
||||||
<img src="html.icons/python.gif"><p>
|
|
||||||
|
|
||||||
This should give you a text window with an informative version string
|
|
||||||
and a prompt, something like the following:
|
|
||||||
<PRE>
|
|
||||||
Python 1.5.1 (#122 Aug 27, 1997) [CW PPC w/GUSI MSL]
|
|
||||||
Copyright 1991-1997 Stichting Mathematisch Centrum, Amsterdam
|
|
||||||
>>>
|
|
||||||
</PRE>
|
|
||||||
The version string tells you the version of Python, whether it was
|
|
||||||
built for PPC or 68K macs and possibly some options used to build the
|
|
||||||
interpreter. If you find a bug or have a question about how the
|
|
||||||
interpreter works it is a good idea to include the version information
|
|
||||||
in your message. <p>
|
|
||||||
|
|
||||||
At the prompt you can type interactive python commands. See the
|
|
||||||
tutorial for more information. The interactive window works
|
|
||||||
more-or-less like a Communication Toolbox or Telnet window: you type
|
|
||||||
commands at the bottom and terminate them with the <EM>[return]</EM>
|
|
||||||
or <EM>[enter]</EM> key. Interpreter feedback also appears at the
|
|
||||||
bottom of the window, and the contents scroll as output is added. You
|
|
||||||
can use copy and paste in the normal way, but be sure to paste only at
|
|
||||||
the bottom of the document.
|
|
||||||
|
|
||||||
<h2>Creating Python scripts</h2>
|
|
||||||
|
|
||||||
The Python interpreter works in a way that is different from what you
|
|
||||||
would expect of a macintosh program: the interpreter is just that: an
|
|
||||||
interpreter. There is no builtin editor or other development
|
|
||||||
support. Hence, to create a Python script you need an external text
|
|
||||||
editor. For a first script you can use any editor that can create
|
|
||||||
plain, unstyled text files, such as <CODE>SimpleText</CODE>. <p>
|
|
||||||
|
|
||||||
For more serious scripts, though, it is advisable to use a programmers
|
|
||||||
editor, such as <CODE>BBEdit</CODE> or <CODE>Alpha</CODE>. BBEdit is
|
|
||||||
my favorite: it comes in a commercial version but also in a
|
|
||||||
fully-functional free version <CODE>BBEdit Lite</CODE>. You can
|
|
||||||
download it from the <A HREF="http://www.barebones.com/">BareBones</A>
|
|
||||||
site. The free version will probably provide all the functionality
|
|
||||||
you will ever need. Besides the standard edit facilities it has
|
|
||||||
multi-file searches and many other goodies that can be very handy when
|
|
||||||
editing programs. <p>
|
|
||||||
|
|
||||||
After you have created your script in the editor of your choice you
|
|
||||||
drop it on the interpreter. This will start the interpreter executing
|
|
||||||
the script, again with a console window in which the output appears
|
|
||||||
and in which you can type input if the script requires it. Normally
|
|
||||||
the interpreter will close the window and quit as soon as the script
|
|
||||||
is done executing, see below under <A HREF="#startup">startup
|
|
||||||
options</A> for a way to change this. <p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
There is a BBEdit extension available that allows you to run Python
|
|
||||||
scripts more-or-less straight from your bbedit source window. Check
|
|
||||||
out the <code>Mac:Tools:BBPy</code> folder.
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
It is a good idea to have the names of all your scripts end in
|
|
||||||
<CODE>.py</CODE>. While this is not necessary for standalone scripts
|
|
||||||
it is needed for modules, and it is probably a good idea to start the
|
|
||||||
habit now. <p>
|
|
||||||
|
|
||||||
If you do not like to start the Python interpreter afresh for each
|
|
||||||
edit-run cycle you can use the <CODE>import</CODE> statement and
|
|
||||||
<CODE>reload()</CODE> function to speed things up in some cases. Here
|
|
||||||
is Guido's original comment for how to do this, from the 1.1 release
|
|
||||||
notes: <P>
|
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
|
|
||||||
Make sure the program is a module file (filename must be a Python
|
|
||||||
identifier followed by '<CODE>.py</CODE>'). You can then import it
|
|
||||||
when you test it for the first time. There are now three
|
|
||||||
possibilities: it contains a syntax error; it gets a runtime error
|
|
||||||
(unhandled exception); or it runs OK but gives wrong results. (If it
|
|
||||||
gives correct results, you are done testing and don't need to read the
|
|
||||||
rest of this paragraph. :-) Note that the following is not
|
|
||||||
Mac-specific -- it's just that on UNIX it's easier to restart the
|
|
||||||
entire script so it's rarely useful. <P>
|
|
||||||
|
|
||||||
Recovery from a syntax error is easy: edit the file and import it
|
|
||||||
again. <P>
|
|
||||||
|
|
||||||
Recovery from wrong output is almost as easy: edit the file and,
|
|
||||||
instead of importing it, call the function <CODE>reload()</CODE> with
|
|
||||||
the module name as argument (e.g., if your module is called
|
|
||||||
<CODE>foo</CODE>, type <CODE>reload(foo)</CODE>). <P>
|
|
||||||
|
|
||||||
Recovery from an exception is trickier. Once the syntax is correct, a
|
|
||||||
'module' entry is placed in an internal table, and following import
|
|
||||||
statements will not re-read the file, even if the module's
|
|
||||||
initialization terminated with an error (one reason why this is done
|
|
||||||
is so that mutually recursive modules are initialized only once). You
|
|
||||||
must therefore force re-reading the module with <CODE>reload()</CODE>,
|
|
||||||
however, if this happens the first time you try to import the module,
|
|
||||||
the import statement itself has not completed, and your workspace does
|
|
||||||
not know the module name (even though the internal table of moduesl
|
|
||||||
does!). The trick is to first import the module again, then reload
|
|
||||||
it. For instance, <CODE>import foo; reload(foo)</CODE>. Because the
|
|
||||||
module object already exists internally, the import statement does not
|
|
||||||
attempt to execute the module again -- it just places it in your
|
|
||||||
workspace. </BLOCKQUOTE>
|
|
||||||
|
|
||||||
<h2>Clickable python scripts</h2>
|
|
||||||
|
|
||||||
If you create your script with the correct creator and type, creator
|
|
||||||
<CODE>'Pyth'</CODE> and type <CODE>'TEXT'</CODE>, you can double-click
|
|
||||||
your script and it will automatically invoke the interpreter. If you
|
|
||||||
use BBEdit you can tell it about the Python file type by adding it to
|
|
||||||
the "file types" sections of the preferences. Then, if you save a file
|
|
||||||
for the first time you can tell BBEdit to save the file as a Python
|
|
||||||
script through the "options" choice of the save dialog. <p>
|
|
||||||
|
|
||||||
The <CODE>Scripts</CODE> folder contains a script
|
|
||||||
<CODE>fixfiletypes</CODE> that will recursively traverse a folder and
|
|
||||||
set the correct creator and type for all files ending in
|
|
||||||
<CODE>.py</CODE>. <p>
|
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
Older releases of Python used the creator code
|
|
||||||
<CODE>'PYTH'</CODE> in stead of <CODE>'Pyth'</CODE>. If you still have
|
|
||||||
older Python sources on your system and named them with
|
|
||||||
<CODE>'.py'</CODE> extension the <CODE>fixfiletypes</CODE> script will
|
|
||||||
correct them.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<h2>Interaction with the user</h2>
|
|
||||||
|
|
||||||
Normally, the interpreter will check for user input (mouse clicks,
|
|
||||||
keyboard input) every once in a while, so it is possible to switch to
|
|
||||||
other applications while a script runs. It is also possible to
|
|
||||||
interrupt the interpreter with the standard command-period keypress,
|
|
||||||
this will raise the <CODE>KeyboardInterrupt</CODE> exception. Scripts
|
|
||||||
may, however, turn off this behaviour to facilitate their own event
|
|
||||||
handling. Such scripts can only be killed with the
|
|
||||||
command-option-escape shortcut.
|
|
||||||
|
|
||||||
<h2><A NAME="startup">startup options</A></h2>
|
|
||||||
|
|
||||||
If the <EM>option</EM> key is depressed when Python starts executing
|
|
||||||
the interpreter will bring up an options dialog thru which you can
|
|
||||||
influence the way the interpreter behaves. Keep the option key
|
|
||||||
depressed until the dialog comes up. <p>
|
|
||||||
|
|
||||||
<img src="html.icons/options.gif"><p>
|
|
||||||
|
|
||||||
The options modify the interpreters behaviour in the following way:
|
|
||||||
<ul>
|
|
||||||
<li> the interpreter goes to interactive mode (in stead of
|
|
||||||
exiting) after a script has terminated normally,
|
|
||||||
<li> for every module imported a line is printed telling you where the
|
|
||||||
module was loaded from,
|
|
||||||
<li> do not print the values of expressions executed as statements in
|
|
||||||
an interactive python (obsolete),
|
|
||||||
<li> do not buffer stdout and stderr,
|
|
||||||
<li> print some debugging output during the parsing phase,
|
|
||||||
<li> keep the output window open when a script terminates.
|
|
||||||
</ul>
|
|
||||||
In addition, you can enter a unix-style command line which is passed
|
|
||||||
to the script in <CODE>sys.argv</CODE>. Sys.argv[0] is always the name
|
|
||||||
of the script being executed, additional values can be passed
|
|
||||||
here. Quoting works as expected. <p>
|
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<EM>Warning:</EM> redirecting standard input or standard output in the
|
|
||||||
command-line dialog does not work. This is due to circumstances beyond my
|
|
||||||
control, hence I cannot say when this will be fixed.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
The default options are also settable on a system-wide basis, see the
|
|
||||||
section on <A HREF="#preferences">editing preferences</A>. <p>
|
|
||||||
|
|
||||||
<h2>Module search path</h2>
|
|
||||||
|
|
||||||
The module search path, <CODE>sys.path</CODE>, contains the folders
|
|
||||||
python will search when you import a module. The path is settable on a
|
|
||||||
system-wide basis (see the preferences section), and normally
|
|
||||||
comprises the current folder (where the script lives), the
|
|
||||||
<CODE>Lib</CODE> folder and some of its subfolders and possibly some
|
|
||||||
more. <p>
|
|
||||||
|
|
||||||
<h2>Working folder</h2>
|
|
||||||
|
|
||||||
The unix concept of a <I>working directory</I> does not translate
|
|
||||||
directly to a similar concept on the Macintosh. To facilitate easy
|
|
||||||
porting and the use of relative pathnames in scripts the interpreter
|
|
||||||
simulates a working directory. When a script is started the initial
|
|
||||||
working directory is the folder where the script lives. In case of an
|
|
||||||
interactive interpreter the working directory is the folder where the
|
|
||||||
interpreter lives. <P>
|
|
||||||
|
|
||||||
By the way: the "standard file" folder, the folder that is presented
|
|
||||||
to the user initially for an <I>open</I> or <I>save</I> dialog, does
|
|
||||||
<EM>not</EM> follow the Python working directory. Which folder is
|
|
||||||
initially shown to the user is usually one of (a) the application
|
|
||||||
folder, (b) the "Documents" folder or (c) the folder most recently
|
|
||||||
used for such a dialog (in any Python program). This is standard MacOS
|
|
||||||
behaviour, so don't blame Python for it. The exact behaviour is
|
|
||||||
settable through a control panel since System 7.5.
|
|
||||||
|
|
||||||
<h2>Interactive startup file</h2>
|
|
||||||
|
|
||||||
If the folder containing the interpreter contains a file named
|
|
||||||
<CODE>PythonStartup</CODE> this file is executed when you start an
|
|
||||||
interactive interpreter. In this file you could import modules you
|
|
||||||
often use and other such things. <p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>Compiled python scripts</h2>
|
|
||||||
|
|
||||||
Once a python module has been imported the interpreter creates a
|
|
||||||
compiled version which is stored in a file with the ".py" extension
|
|
||||||
replaced by ".pyc". These compiled files, with creator
|
|
||||||
<CODE>'Pyth'</CODE> and type <CODE>'PYC '</CODE> load faster when
|
|
||||||
imported (because they do not have to be parsed). The <CODE>Lib</CODE>
|
|
||||||
folder contains a script <CODE>compileall.py</CODE>, running this
|
|
||||||
script will cause all modules along the python search path to be
|
|
||||||
precompiled, which will speed up your programs. Compiled files are
|
|
||||||
also double-clickable. <p>
|
|
||||||
|
|
||||||
<h2>Python resources</h2>
|
|
||||||
|
|
||||||
MacPython has the ability to collect a number of compiled modules
|
|
||||||
together in the resource fork of a single file. This feature is useful
|
|
||||||
if you distribute a python program and want to minimize clutter: you
|
|
||||||
can put all the needed modules in a single file (which could even be
|
|
||||||
the interpreter itself). <p>
|
|
||||||
|
|
||||||
If the module search path contains a filename as one of its entries
|
|
||||||
(as opposed to a folder name, which is the normal case) this file will
|
|
||||||
be searched for a resource with type <CODE>'PYC '</CODE> and a name
|
|
||||||
matching the module being imported. <p>
|
|
||||||
|
|
||||||
The <CODE>scripts</CODE> folder contains a script
|
|
||||||
<CODE>PackLibDir</CODE> which will convert a number of modules (or
|
|
||||||
possibly a complete subtree full of modules) into such a resource
|
|
||||||
file.
|
|
||||||
|
|
||||||
<h2><A NAME="preferences">Setting interpreter preferences</A></h2>
|
|
||||||
|
|
||||||
The python interpreter keeps a preferences file in the standard
|
|
||||||
location in the system folder. In this preferences file it remembers
|
|
||||||
the default module search path and the default settings for the
|
|
||||||
runtime options. The preferences are settable via
|
|
||||||
<CODE>EditPythonPrefs</CODE>. For PPC/cfm68k python this is a standalone
|
|
||||||
program living in the main Python folder, for 68K python it is a
|
|
||||||
script in the <CODE>Mac:Scripts</CODE> folder. <p>
|
|
||||||
|
|
||||||
The interface to edit the preferences is rather clunky for the current
|
|
||||||
release. <p>
|
|
||||||
|
|
||||||
<img src="html.icons/preferences.gif"><p>
|
|
||||||
|
|
||||||
In the editable text field at the top you enter the initial module
|
|
||||||
search path, using newline as a separator. There are two special
|
|
||||||
values you can use here: an initial substring <CODE>$(PYTHON)</CODE>
|
|
||||||
will expand to the Python home folder and a value of
|
|
||||||
<CODE>$(APPLICATION)</CODE> will expand to the the python application
|
|
||||||
itself. Note that the text field may extend "beyond the bottom" even
|
|
||||||
though it does not have a scroll bar. Using the arrow keys works,
|
|
||||||
though.<p>
|
|
||||||
|
|
||||||
The Python home folder $(PYTHON) is initially, when you install Python,
|
|
||||||
set to the folder where the interpreter lives. You can change it here. <p>
|
|
||||||
|
|
||||||
Finally, you can set the default startup options here, through a
|
|
||||||
sub-dialog.
|
|
||||||
|
|
||||||
<h2>Applets</h2>
|
|
||||||
|
|
||||||
An applet is a fullblown application written in Python, similar to an
|
|
||||||
AppleScript applet (and completely different from a Java
|
|
||||||
applet). Applets are currently supported on PowerPC macintoshes and on
|
|
||||||
68K macintoshes if you use the CFM68K version of the interpreter,
|
|
||||||
and are created using the <CODE>BuildApplet</CODE> program. You create an
|
|
||||||
applet by dropping the python source script onto BuildApplet.
|
|
||||||
<a href="example2.html">Example 2</a> is a more involved applet
|
|
||||||
with its own resource file, etc. <p>
|
|
||||||
|
|
||||||
Note that while an applet behaves as a fullblown Macintosh application
|
|
||||||
it is not self-sufficient, so distributing it to a machine without an
|
|
||||||
installed Python interpreter will not work: it needs the shared python
|
|
||||||
execution engine <CODE>PythonCore</CODE>, and probably various modules
|
|
||||||
from the Lib and PlugIns folders. Distributing it to a machine that does
|
|
||||||
have a Python system will work. <p>
|
|
||||||
|
|
||||||
<h2>Customizing applets</h2>
|
|
||||||
|
|
||||||
Applets can have their own settings for the startup options and module
|
|
||||||
search path. Dropping an applet on the <CODE>EditPythonPrefs</CODE>
|
|
||||||
application allows you to set these, in the same way as
|
|
||||||
double-clicking EditPythonPrefs allows you to set the system-wide
|
|
||||||
defaults. <p>
|
|
||||||
|
|
||||||
Actually, not only applets but also the interpreter itself can have
|
|
||||||
non-default settings for path and options. If you make a copy of the
|
|
||||||
interpreter and drop this copy onto EditPythonPrefs you will have an
|
|
||||||
interpreter that has a different set of default settings. <p>
|
|
||||||
|
|
||||||
<h2>Where to go from here</h2>
|
|
||||||
|
|
||||||
The previously mentioned <A
|
|
||||||
HREF="http://www.python.org/doc/tut/tut.html">Python Tutorial</A> is
|
|
||||||
an excellent place to start reading if you have never used Python
|
|
||||||
before. Other documentation such as the library reference manual is
|
|
||||||
indexed at the <A HREF="http://www.python.org/doc/">Python
|
|
||||||
Documentation</A> page. <p>
|
|
||||||
|
|
||||||
There are some <A HREF="index.html">annotated sample programs</A>
|
|
||||||
available that show some mac-specific issues, like use of various
|
|
||||||
toolboxes and creation of Python applets. <p>
|
|
||||||
|
|
||||||
The <CODE>Demo</CODE> and <CODE>Mac:Demo</CODE>
|
|
||||||
folders in the Macintosh distribution
|
|
||||||
contains a number of other example programs. Most of these are only
|
|
||||||
very lightly documented, but they may help you to understand some
|
|
||||||
aspects of using Python. <p>
|
|
||||||
|
|
||||||
Finally, there is a <code>Mac:Contrib</code> folder that contains
|
|
||||||
a few contributions to Python that I couldn't fit in the normal tree
|
|
||||||
but did want to distribute (many other contributions are contained
|
|
||||||
throughout the distribution, but you don't see them, really).
|
|
||||||
|
|
||||||
The best way to contact fellow Macintosh Python programmers is to join
|
|
||||||
the MacPython Special Interest Group mailing list. Send a message with
|
|
||||||
"info" in the body to <A
|
|
||||||
HREF="mailto:pythonmac-sig-request@python.org">pythonmac-sig-request@python.org</A>
|
|
||||||
or view the <A
|
|
||||||
HREF="http://www.python.org/sigs/pythonmac-sig/">Pythonmac SIG
|
|
||||||
page</A> on the <A HREF="http://www.python.org">www.python.org</A> WWW
|
|
||||||
server. <p>
|
|
||||||
|
|
||||||
<h2>Troubleshooting</h2>
|
|
||||||
|
|
||||||
A rather baffling error message can be "PythonCore not found" when you
|
|
||||||
start the interpreter and you are sure that PythonCore is available. The
|
|
||||||
message should actually say "Not enough memory in the system heap to
|
|
||||||
load PythonCore".
|
|
||||||
Blame Apple for the confusing message. <p>
|
|
||||||
|
|
||||||
There appear to be problems with QuickTime for the CFM68K version of the
|
|
||||||
interpreter. If you experience these please contact the SIG: some people
|
|
||||||
use quicktime without problems and some not, and we are still hunting for
|
|
||||||
the cause. <p>
|
|
||||||
|
|
||||||
Python is a rather safe language, and hence it should be difficult to
|
|
||||||
crash the interpreter of the system with a Python script. There is an
|
|
||||||
exception to this rule, though: the modules that interface to the
|
|
||||||
system toolboxes (windowing, quickdraw, etc) do very little error
|
|
||||||
checking and therefore a misbehaving program using these modules may
|
|
||||||
indeed crash the system. Such programs are unfortunately rather
|
|
||||||
difficult to debug, since the crash does not generate the standard
|
|
||||||
Python stack trace, obviously, and since debugging print statements
|
|
||||||
will often interfere with the operation of the program. There is
|
|
||||||
little to do about this currently. <p>
|
|
||||||
|
|
||||||
Probably the most common cause of problems with modules ported from
|
|
||||||
other systems is the Mac end-of-line convention. Where unix uses
|
|
||||||
linefeed, 0x0a, to separate lines the mac uses carriage return,
|
|
||||||
0x0d. To complicate matters more a lot of mac programming editors like
|
|
||||||
BBEdit and emacs will work happily with both conventions, so the file
|
|
||||||
will appear to be correct in the editor but cause strange errors when
|
|
||||||
imported. BBEdit has a popup menu which allows you to inspect (and
|
|
||||||
set) the end-of-line convention used in a file. <p>
|
|
||||||
|
|
||||||
Python attempts to keep its preferences file up-to-date even when you
|
|
||||||
move the Python folder around, etc. If this fails the effect will be
|
|
||||||
that Python cannot start or, worse, that it does work but it cannot find
|
|
||||||
any standard modules. In this case, start Python and examine <code>sys.path</code>.
|
|
||||||
If it is incorrect remove any Python preferences file from the system
|
|
||||||
folder and start the interpreter <em>while the interpreter sits in the main
|
|
||||||
Python folder</em>. This will regenerate the preferences file. You may also
|
|
||||||
have to run the ConfigurePython applet again. <p>
|
|
||||||
|
|
||||||
<h2>Your five minutes are up. Next!</h2>
|
|
||||||
|
|
||||||
The next section to check out is the <a href="index.html">annotated sample programs</a>.<p>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
|
|
||||||
<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 10-Sep-00.
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
Loading…
Reference in New Issue