如何在Python中检查一个对象是否为PyCapsule?

3

我有一个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

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)

你需要以某种方式获取类对象的范围,可以通过导入它或者在这里,你可以简单地执行 PyCapsule = type(capsule) 然后使用 isinstance(whatever, PyCapsule) - juanpa.arrivillaga
@juanpa.arrivillaga 我正在寻找导入它的方法;我想要做的是编写一个函数来检查用户是否传递了 PyCapsule,而不必实例化一个 PyCapsule 并提取类型。我已更新我的 OP 以包括这一点。 - Matthew Moisen
很遗憾,它可能不会在任何地方公开作为导入。但是,在全局范围内实例化一个 PyCapsule 来获取其类型有什么坏处呢? - juanpa.arrivillaga
@juanpa.arrivillaga 如果它没有在任何地方公开作为导入,我认为我可能不得不这样做。 - Matthew Moisen
嗯,那听起来像是一个解决方案。虽然有点不太优雅,但并不特别糟糕。 - juanpa.arrivillaga
3个回答

6

正如您所指出的那样,PyCapsule类型不能直接从Python中访问。为了在没有重度依赖ctypes的情况下检测它(在DavidW的答案中被接受),我会改为执行以下操作:

def is_capsule(o):
    t = type(o)
    return t.__module__ == 'builtins' and t.__name__ == 'PyCapsule'

2

虽然有点混乱,但你可以从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_object似乎需要一个包含PyObject*的地址,而不是PyObject*本身,因此需要额外的间接层。

1

通常情况下,首先检查您的API是否提供了访问您想引用的类的方法。

如果没有提供该方法,则可以从虚拟实例中恢复该类。

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

...

if isinstance(bar, PyCapsule):
    ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接