Python/C API: Python class instance information in C?

Bernt Ribbum bernt at tordivel.no
Fri Mar 21 10:10:13 CET 2003


Thanks Alex,

The trick was to use the Object Protocol -- there I can find anything I
want.

(And thanks for compiling the Python Cookbook. That one is invaluable
sometimes ;-)

--

- Bernt
---------------------------------------------------------------------------
TORDIVEL AS  http://www.tordivel.no
Storgata 20  0184 OSLO  NORWAY
Tel +47 2315 8700  Fax +47 2315 8701
Bernt Ribbum  bernt at tordivel.no  bernt.ribbum at ieee.org
Direct: +47 2315 8714  Mobile: +47 906 106 85
---------------------------------------------------------------------------

"Alex Martelli" <aleax at aleax.it> wrote in message
news:AyAea.92650$pG1.2015177 at news1.tin.it...
> <posted & mailed>
>
> Bernt Ribbum wrote:
>
> > In a C module function, is it possible to extract information about a
> > Python class instance being sent as argument?
>
> Yes.  You can basically do in your C code all that you might do from
> Python code, albeit more clumsily and less productively of course. And
> this in particular applies to introspection, as well as other tasks.
>
>
> > To explain a bit further... A C module (METH_VARARGS wrapper) function
> > prototype looks something like
> >
> > PyObject *spam_func(PyObject *self, PyObject *args);
> >
> > The Python arguments are found (possibly inside a tuple) in "args", and
I
> > can handle this for standard Python types like ints, floats, etc., and
> > also for types exported from my C module. What I stumble on, is Python
> > code like this:
> >
> > import spam
> > class X:
> >   pass
> > x = X()
> > spam.func(x)
> >
> > In this case I don't know how to extract information about the object.
All
> > I can find (from the C debugger) is that the object in question has an
> > ob_type of _PyInstance_Type. (A call to PyInstance_Check() will return
> > true, but unfortunately the documentation states "There are very few
> > functions specific to instance objects". In fact, there is only the
check
> > function above and two New functions. Nothing else.)
> >
> > Is it possible for me to get more information here? I would like to
know,
> > at least, that this object is of type "class X" or similar.
>
> By PyInstance_Check you identify instances of CLASSIC classes only, of
> course; i.e. if in your example above X inherited from object (and thus
> was a newstyle class) its instances wouldn't pass PyInstance_Check.  If
> you also want to handle instances of newstyle classes you'll have to
> work those differently.  But let's focus for now on classic class
isntances.
>
> However, the general idea is that you work with the abstract protocol,
> i.e. the PyObject_... functions, getting the relevant attributes.  Here
> is one silly example (not thoroughly tested) -- save as intro.py:
>
> #include <Python.h>
> #include <stdio.h>
>
> static PyObject*
> intro(PyObject* self, PyObject* args)
> {
>     PyObject *theobj, *theclas, *thecnam;
>     if(!PyArg_ParseTuple(args, "O", &theobj))
>         return 0;
>     if(PyInstance_Check(theobj)) {
>         printf("Is an instance.\n");
>         theclas = PyObject_GetAttrString(theobj, "__class__");
>         if(!theclas)
>             return 0;
>         thecnam = PyObject_GetAttrString(theclas, "__name__");
>         if(!thecnam) {
>             Py_DECREF(theclas);
>             return 0;
>         }
>         if(!PyString_Check(thecnam)) {
>             Py_DECREF(theclas);
>             Py_DECREF(thecnam);
>             return PyErr_Format(PyExc_RuntimeError,
>                 "class name is not a string (?)");
>         }
>         printf("of class %s\n", PyString_AS_STRING(thecnam));
>         Py_DECREF(theclas);
>         Py_DECREF(thecnam);
>     } else {
>         printf("Not an instance.\n");
>     }
>     return Py_BuildValue("");
> }
>
> static PyMethodDef introMethods[] = {
>     {"intro", intro, METH_VARARGS, "introspection example"},
>     {0}
> };
>
> void
> initintro(void)
> {
>     Py_InitModule("intro", introMethods);
> }
>
> and build/install with the usual setup.py:
>
> from distutils.core import setup, Extension
>
> setup(name = "intro",
>     version = "1.0",
>     description = "introspection from C",
>     maintainer = "Alex Martelli",
>     maintainer_email = "aleaxit at yahoo.com",
>
>     ext_modules = [ Extension('intro', sources=['intro.c']) ]
> )
>
>
> Now for example:
>
> >>> import intro
> >>> intro.intro(23)
> Not an instance.
> >>> class X: pass
> ...
> >>> intro.intro(X())
> Is an instance.
> of class X
> >>>
>
>
>
> Alex
>






More information about the Python-list mailing list