Casting Python objects to void*

1,045 views
Skip to first unread message

Antony Lee

unread,
Dec 8, 2015, 8:18:21 PM12/8/15
to cython...@googlegroups.com
Casting a python object to e.g. an <int*> fails (correctly, in my opinion) with the error message "Python objects cannot be cast to pointers of primitive types".  However, this is not the case for <void*>, as can be seen with the following example:

def main():
    cdef double data = 123
    cdef list l = []
    l.append(<size_t>&data)
    cdef void* ptr = <void*>l[0]
    print((<double*>ptr)[0])

This will not print out 123 :-(
Use-case: I want to store a bunch of void pointers as integers (by casting to size_t) in a python list.  When retrieving the pointers from the list, <void*>l[0] fails silently as shown by the example.  A workaround is to write <void*><size_t>l[0] which works, but a more explicit error message would have saved me a couple of hours.

Best,
Antony

Robert Bradshaw

unread,
Dec 8, 2015, 8:29:52 PM12/8/15
to cython...@googlegroups.com
I agree that the ambiguity

cdef object o = ...
cdef void* ptr = <void*>o

when o happens to be a Python int is unfortunate, but casting objects
to void* is quite common for letting them propagate through C
libraries (e.g. as fake closures/state for callbacks) so I don't think
we want to make this an error.

- Robert

Antony Lee

unread,
Dec 8, 2015, 10:12:31 PM12/8/15
to cython...@googlegroups.com
Wouldn't the proper way to do this be a cast to <PyObject*> instead?  You could make <PyObject*> implicitly cast-able to <void*> to avoid boilerplate.

In fact the current behavior has some funny interactions with infer_types:


 def main():
    cdef double data = 123
    addr = <size_t>&data
    cdef void* ptr = <void*>addr

    print((<double*>ptr)[0])

This prints 123 when infer_types is unset or True, but some random value if infer_types is False.

Antony
Reply all
Reply to author
Forward
0 new messages