This page contains supplemental material for this March 1997 presentation. It includes directions for running the installed Python interpreter, and a few extra Python/C(++) integration examples not included in the original talk. Some of this was derived from a page I kept for a company I worked at, but it's mostly general information.
Update: also see the new integration examples page.
The following csh script shows how to configure the Python (and Tk) environment variables:
file: runpy #!/bin/csh # # file: runpy # Give this file executable privileges (chmod +x runpy). # You could also put the set/setenv's in your .cshrc instead. # # 1) Add path to command-line interpreter set path = (/opt/local/sparc-solaris-2.4/bin $path) # 2) Set python library search paths # not really needed -> standard paths are hard-coded in interpreter # add your module file working directories to the list as desired setenv PYTHONPATH /opt/local/lib/python1.4:/opt/local/lib/python1.4/tkinter # 3) Set tk library search paths (for GUIs) setenv TCL_LIBRARY /opt/local/lib/tcl7.4 setenv TK_LIBRARY /opt/local/lib/tk4.0 # 4) Start up the command-line python1.4
Now, run the command-line interpreter from the UNIX shell like this, and type in Python statements and expressions:
zppa% runpy Python 1.4 (Mar 6 1997) [GCC 2.7.2] Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam >>> >>> from Tkinter import * >>> w = Button(text="Hello", command='exit') >>> w.pack() >>> w.mainloop()
If everything is set up right, you'll get a simple 1-button window on your X display (what $DISPLAY names). Of course, this is just one way to run Python. You can also assign the environment variables in your .cshrc/.kshrc file, and/or:
Note: start-up details differ on Windows and Macs; see the section on ways to run Python programs in the talk material.
The file below implements a C extension module for Python, called "environ". It wraps the C library's getenv routine for use in Python programs like this:
>>> import environ >>> name = environ.getenv("USER")
To bind it into Python, add a line to Modules/Setup like "environ environ.c", put (or link) the file in Modules, and re-make python. Alternatively, compile to a .so, and add its path to $PYTHONPATH (dynamically loads when first imported).
file: environ.c #include <Python.h> #include <stdlib.h> /* Functions */ static PyObject * /* returns object */ wrap_getenv(PyObject *self, PyObject *args) /* self not used */ { /* args from python */ char *varName, *varValue; PyObject *returnObj = NULL; /* null=exception */ if (PyArg_Parse(args, "s", &varName)) /* Python -> C */ if ((varValue = getenv(varName)) != NULL) /* call C getenv */ returnObj = Py_BuildValue("s", varValue); /* C -> Python */ else PyErr_SetString(PyExc_SystemError, "Error calling getenv"); else PyErr_SetString(PyExc_TypeError, "Usage: getenv(varName)"); return returnObj; } /* Registration */ static struct PyMethodDef environ_methods[] = { {"getenv", wrap_getenv}, /* name, address */ {NULL, NULL} }; /* Initialization */ void initenviron() /* this is called by Python */ { /* on first "import environ" */ (void) Py_InitModule("environ", environ_methods); }
file: embed.c #include <Python.h> main(argc, argv) int argc; char **argv; { /* This is the simplest embedding mode. */ /* Other API functions return results, */ /* accept namespace arguments, allow */ /* access to real Python objects, etc. */ /* Strings may be precompiled for speed. */ Py_Initialize(); /* initialize python */ PyRun_SimpleString("print 'Hello embedded world!'"); /* run python code */ /* use C extension module above */ PyRun_SimpleString("from environ import *"); PyRun_SimpleString( "for i in range(5):\n" "\tprint i,\n" "\tprint 'Hello, %s' % getenv('USER')\n\n" ); PyRun_SimpleString("print 'Bye embedded world!'"); } char *Py_GetProgramName() { return "embed"; } /* not always needed */ file: Makefile PY = /opt/local/src/Python-1.4-embed/Python-1.4 PLIBS = $(PY)/Modules/libModules.a \ $(PY)/Python/libPython.a \ $(PY)/Objects/libObjects.a \ $(PY)/Parser/libParser.a POBJS = $(PY)/Modules/config.o $(PY)/Modules/getpath.o embed: embed.o cc embed.o $(POBJS) $(PLIBS) -lm -o embed embed.o: embed.c cc embed.c -c -I$(PY)/Include -I$(PY)/.
Here's one way to do it using builtin API calls, less the error checking that you should normally do after each "Py*" API call. Check for NULL pointer results, etc., to detect errors in Python. Link with Python .a/.o's, and put module.py's dir in PYTHONPATH.
file: module.py class klass: def method(self, x, y): return "brave %s %s" % (x, y) # run me from C file: mymain1.c #include <Python.h> #include <import.h> #include <stdio.h> char *Py_GetProgramName() { return "mymain1"; } main() { char *arg1="sir", *arg2="robin", *cstr; PyObject *pmod, *pclass, *pargs, *pinst, *pmeth, *pres; /* make module.class instance */ Py_Initialize(); pmod = PyImport_ImportModule("module"); /* fetch module */ pclass = PyObject_GetAttrString(pmod, "klass"); /* fetch module.class */ Py_DECREF(pmod); pargs = Py_BuildValue("()"); pinst = PyEval_CallObject(pclass, pargs); /* call class() */ Py_DECREF(pclass); Py_DECREF(pargs); /* call instance.method */ pmeth = PyObject_GetAttrString(pinst, "method"); /* fetch bound method */ Py_DECREF(pinst); pargs = Py_BuildValue("(ss)", arg1, arg2); /* convert to Python */ pres = PyEval_CallObject(pmeth, pargs); /* call method(x,y) */ Py_DECREF(pmeth); Py_DECREF(pargs); PyArg_Parse(pres, "s", &cstr); /* convert to C */ printf("%s\n", cstr); Py_DECREF(pres); } % mymain1 brave sir robin
This version uses the pyembed higher-level embedding interface. The interface also includes code string calls, etc. This approach can be simpler (especially if you add all the error detection logic to the example above). Compile with the "pyembed*.c" files from the book "Programming Python", chapter 15.
file: mymain2.c #include <stdio.h> #include "pyembed.h" char *Py_GetProgramName() { return "mymain2"; } main () { int status; PyObject *pinst; char *arg1="sir", *arg2="robin", *cstr; status = Run_Function("module", "klass", "O", &pinst, "()"); status = Run_Method(pinst, "method", "s", &cstr, "(ss)", arg1, arg2); printf("%s\n", cstr); Py_DECREF(pinst); } % mymain2 brave sir robin
Back to talk material root page