[Python-Dev] ctypes: is it intentional that id() is the only way to get the address of an object?
Steve Dower
steve.dower at python.org
Fri Jan 18 01:09:36 EST 2019
For everyone who managed to reply *hours* after Eryk Sun posted the
correct answer and still get it wrong, here it is again in full.
As a bonus, here's a link to the place where this answer appears in the
documentation:
https://docs.python.org/3/library/ctypes.html#ctypes.py_object
Cheers,
Steve
On 17Jan.2019 0550, eryk sun wrote:
> On 1/17/19, Steven D'Aprano <steve at pearwood.info> wrote:
>>
>> I understand that the only way to pass the address of an object to
>> ctypes is to use that id. Is that intentional?
>
> It's kind of dangerous to pass an object to C without an increment of
> its reference count. The proper way is to use a simple pointer of type
> "O" (object), which is already created for you as the "py_object"
> type.
>
> >>> ctypes.py_object._type_
> 'O'
> >>> ctypes.py_object.__bases__
> (<class '_ctypes._SimpleCData'>,)
>
> It keeps a reference in the readonly _objects attribute. For example:
>
> >>> b = bytearray(b'spam')
> >>> sys.getrefcount(b)
> 2
> >>> cb = ctypes.py_object(b)
> >>> sys.getrefcount(b)
> 3
> >>> cb._objects
> bytearray(b'spam')
> >>> del cb
> >>> sys.getrefcount(b)
> 2
>
> If you need the address without relying on id(), cast to a void pointer:
>
> >>> ctypes.POINTER(ctypes.c_void_p)(cb)[0] == id(b)
> True
>
> Or instantiate a c_void_p from the py_object as a buffer:
>
> >>> ctypes.c_void_p.from_buffer(cb).value == id(b)
> True
>
> Note that ctypes.cast() doesn't work in this case. It's implemented as
> an FFI function that takes the object address as a void pointer. The
> from_param method of c_void_p doesn't support py_object:
>
> >>> ctypes.c_void_p.from_param(cb)
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: wrong type
More information about the Python-Dev
mailing list