1 class _UniffiPointerManagerCPython
:
3 Manage giving out pointers to Python objects on CPython
5 This class is used to generate opaque pointers that reference Python objects to pass to Rust.
6 It assumes a CPython platform. See _UniffiPointerManagerGeneral for the alternative.
9 def new_pointer(self
, obj
):
11 Get a pointer for an object as a ctypes.c_size_t instance
13 Each call to new_pointer() must be balanced with exactly one call to release_pointer()
15 This returns a ctypes.c_size_t. This is always the same size as a pointer and can be
16 interchanged with pointers for FFI function arguments and return values.
18 # IncRef the object since we're going to pass a pointer to Rust
19 ctypes
.pythonapi
.Py_IncRef(ctypes
.py_object(obj
))
20 # id() is the object address on CPython
21 # (https://docs.python.org/3/library/functions.html#id)
24 def release_pointer(self
, address
):
25 py_obj
= ctypes
.cast(address
, ctypes
.py_object
)
27 ctypes
.pythonapi
.Py_DecRef(py_obj
)
30 def lookup(self
, address
):
31 return ctypes
.cast(address
, ctypes
.py_object
).value
33 class _UniffiPointerManagerGeneral
:
35 Manage giving out pointers to Python objects on non-CPython platforms
37 This has the same API as _UniffiPointerManagerCPython, but doesn't assume we're running on
38 CPython and is slightly slower.
40 Instead of using real pointers, it maps integer values to objects and returns the keys as
46 self
._lock
= threading
.Lock()
47 self
._current
_handle
= 0
49 def new_pointer(self
, obj
):
51 handle
= self
._current
_handle
52 self
._current
_handle
+= 1
53 self
._map
[handle
] = obj
56 def release_pointer(self
, handle
):
58 return self
._map
.pop(handle
)
60 def lookup(self
, handle
):
62 return self
._map
[handle
]
64 # Pick an pointer manager implementation based on the platform
65 if platform
.python_implementation() == 'CPython':
66 _UniffiPointerManager
= _UniffiPointerManagerCPython
# type: ignore
68 _UniffiPointerManager
= _UniffiPointerManagerGeneral
# type: ignore