Reputation: 18299
I have a C Extension that receives and accepts PyCapsule objects.
In my python wrapper, how can I check if a python object is of the PyCapsule type object?
>>> # My C extension
>>> foo = Foo()
>>> capsule = foo.to_capsule() # returns a PyCapsule object from the C extension
>>> capsule
<capsule object "foo" at 0xf707df08>
>>> type(capsule)
<class 'PyCapsule'>
isinstance(capsule, PyCapsule)
NameError: name 'PyCapsule' is not defined
What I'm trying to do is write a function like:
def push_capsule(capsule):
# check that the `capsule` is of type PyCapsule
# c_extension.push_capsule(capsule)
Upvotes: 3
Views: 3416
Reputation: 30931
It's a bit of a mess but you can get it from ctypes
:
def get_capsule_type():
class PyTypeObject(ctypes.Structure):
pass # don't need to define the full structure
capsuletype = PyTypeObject.in_dll(ctypes.pythonapi, "PyCapsule_Type")
capsuletypepointer = ctypes.pointer(capsuletype)
return ctypes.py_object.from_address(ctypes.addressof(capsuletypepointer)).value
Creating a py_object
from an address looks to require an address which contains a PyObject*
, rather than the PyObject*
itself, hence the extra layer of indirection.
Upvotes: 2
Reputation: 695
The PyCapsule type is not directly accessible from Python as you have noted. To detect it without the heavy ctypes dependency (in the accepted answer by DavidW), I would do the following instead:
def is_capsule(o):
t = type(o)
return t.__module__ == 'builtins' and t.__name__ == 'PyCapsule'
Upvotes: 7
Reputation: 22324
In general, first check if your API offers some way to access the class you want to reference.
If it does not, recover the class from a dummy instance.
PyCapsule = type(Foo().to_capsule())
...
if isinstance(bar, PyCapsule):
...
Upvotes: 1