如何检查Python中的对象是否是PyCapsule?

如何检查Python中的对象是否是PyCapsule?,python,python-3.x,python-c-api,Python,Python 3.x,Python C Api,我有一个C扩展,它接收和接受PyCapsule对象 在我的python包装器中,如何检查python对象是否为PyCapsule类型的对象 >>> # My C extension >>> foo = Foo() >>> capsule = foo.to_capsule() # returns a PyCapsule object from the C extension >>> capsule <capsule o

我有一个C扩展,它接收和接受PyCapsule对象

在我的python包装器中,如何检查python对象是否为PyCapsule类型的对象

>>> # 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

一般来说,首先检查您的API是否提供了某种方式来访问要引用的类

如果没有,则从虚拟实例恢复该类

PyCapsule = type(Foo().to_capsule())

...

if isinstance(bar, PyCapsule):
    ...

这有点乱,但你可以从
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(capsulepointerpointer)).value

从地址创建
py_对象
看起来需要一个包含
PyObject*
的地址,而不是
PyObject*
本身,因此需要额外的间接层。

PyCapsule类型无法从Python直接访问,正如您所指出的。要在没有严重的ctypes依赖性的情况下检测它(在DavidW接受的答案中),我将执行以下操作:

def是_胶囊(o):
t=类型(o)
返回t.uuu模块uuu=='builtins'和t.uu名称uuu=='PyCapsule'

您需要以某种方式获取作用域中的类对象,或者通过导入它,或者在这里,您可以简单地执行
PyCapsule=type(capsule)
然后使用
isinstance(无论如何,PyCapsule)
@juanpa.arrivillaga我正在寻找导入它的方法;我想做的是让函数检查用户是否传入了PyCapsule,而不必实例化PyCapsule并提取类型。我已经更新了我的OP以包含它。不幸的是,它可能不会在任何地方作为导入公开。但是在全局范围内实例化PyCapsule一次,仅仅是为了得到它的类型,有什么害处呢?@juanpa.arrivillaga如果它在任何地方都没有作为导入公开,我想我可能不得不这样做。嗯,这听起来像是一个解决方案。虽然我觉得有点不雅,但也不是特别糟糕。
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(capsulepointerpointer)).value