Type checking inside a C extension

Paul Prescod paul at prescod.net
Mon Apr 5 05:57:50 EDT 2004


Jon Perez wrote:
> 
 > The problem is that neither PyLong_AsLong() nor
 > PyString_AsString() does any type checking so the
 > interpreter crashes when I try to use the values
 > returned by PyLong_AsLong() and PyString_AsString() if
 > they happen to be fed objects - the tuple elements in
 > this case - of the wrong type.

It isn't true that PyLong_AsLong does no type checking. It does. It 
reports problems through the standard Python exception system.

> I could certainly do a type check using PyLong_Check() and 
> PyString_Check() on the tuple items and raise a TypeError exception 
> to avoid leading to a crash, but I am concerned about the speed hit 
> as this is the innermost loop of a routine which gets called really
> often (I use it for text block transfers).


PyLong_Check is pretty cheap:

#define PyObject_TypeCheck(ob, tp) \
         ((ob)->ob_type == (tp) || PyType_IsSubtype((ob)->ob_type, (tp)))
#define PyLong_Check(op) PyObject_TypeCheck(op, &PyLong_Type)

Note that it is basically just a dereference and comparison check. I 
wouldn't worry about that even in an inner loop.

> Is there a less expensive way to check the type, or somehow
> avoid a crashing situation (i.e. an exception gets properly raised)
> without calling PyLong_Check() and PyString_Check() the elements
> of each and every tuple?

I would usually use Pyrex for a job like this. But barring that, I often 
use its output to remember how to do little Python/C things. Given this 
input program:

def foo(b):
         cdef int a
         a = b

it generates code like this:

   /* "/private/tmp/foo.pyx":3 */
   __pyx_1 = PyInt_AsLong(__pyx_v_b);
   if (PyErr_Occurred()) {error handling and return}

By PyErr_Occurred() is a real function call and is probably slower than 
PyLong_Check.

  Paul Prescod






More information about the Python-list mailing list