Using Python As an Extensibility Library

Alex Martelli aleax at aleax.it
Fri Sep 7 08:42:29 EDT 2001


"kmalloc" <kmalloc at hotmail.com> wrote in message
news:fa1faa6a.0109070256.2cc2d875 at posting.google.com...
    ...
> 1) I understand it is possible to run client code using an
> already-set-up context containing classes, variables and functions.

Sure.

> How do I exactly do that?

Several ways, depending on your exact setup.  For example,
if you get a string from somewhere that should be one or
more Python statements, and want to run THAT "client code"
in an "already-set-up context", the key function, quite
akin to Python's exec statement, is:

PyObject* PyRun_String(char *str, int start,
    PyObject *globals, PyObject *locals)

The 'start' symbol is e.g. Py_file_input.  The globals
and locals are Python dictionaries, where you prepare
whatever context you want.  There's a similar PyRun_File
to save you from reading the file into a string in
memory to execute it the same way, if the "somewhere"
you're getting the source code from is a file:-).  Or,
you could access from your C/C++ code Python's standard
rexec module if you can't trust the Python code you're
to run, and so want to restrict its execution.

> 2) I have unsuccessfully tried to programmatically create a Python
> class in an existing module dictionary. All I got was an access
> violation...
> Can anyone explain to me how to do that "the right way"?

Defining Python *classes* in C isn't trivial -- I would
suggest you look into C++ and Boost Python, or Fuller's
ExtensionClass, or other such approaches, if you really
need that (but Python 2.2, when it matures, will probably
let you use a *type*, which you define in C, in a very
close way to a class, so you may not really need it...).
You can probably get away with a type, MUCH easier to
define, and then if need be wrap it in a Python class so
that client code can inherit/override/&c.

You may want to start with a look at
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66509
a truly minimal type defined as a Python extension, with
its factory function and two accessors as sole entries in
their own modules (it doesn't even expose Python-visible
methods or attributes... you can only use it through the
accessors -- that's to make the example really minimal,
although already of some peculiar usefulness:-).

It's not a class, it's a type, so Python code can't
inherit/override, BUT, no worry -- you can also supply
the Python code yourself that *wraps* the bare C type
to make it more Python-friendly, much in the spirit of
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52295
(though you can't directly use that recipe as it relies
on the type it wraps already having attributes, it's not
too hard to adapt it).

Once you have a "PyObject* bleep" of whatever description,
wherever it comes from, and a "PyObject* themod" that is
an existing module already known to Python, it's easy to
make bleep visible to Python as the attribute 'Kook' of
themod: see:
int PyObject_SetAttrString(PyObject *o, char *attr_name, PyObject *v)
and just call PyObject_SetAttrString(themod, "Kook", bleep)
(and check it returns 0, just in case:-).
You can get themod from any of the PyImport... functions,
of course, depending on your exact needs.

Adding your own C-coded modules to Python before you
initialize Python when embedding it is easy -- see
int PyImport_AppendInittab(char *name, void (*initfunc)(void))
(or the more general PyImport_ExtendInittab).  But if
you want the Python snippets you will run to access your
extension-objects without doing import themselves, you'll
probably want to add some of your objects with whatever
names are appropriate to __builtins__...


Alex






More information about the Python-list mailing list