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