【问题标题】:convert python object to cython pointer将python对象转换为cython指针
【发布时间】:2012-12-02 14:00:21
【问题描述】:

我正在尝试使用 cython 将 c++ 类公开给 python。我在 *.pxd 文件中编写了它们的定义,并在 *.pyx 文件中实现了一个包装器。但是我试图将函数指针传递给扩展类型时遇到了困难。这是简化的示例。

foo.pyx

from c_foo cimport cFoo
cdef class Foo:
    cdef cFoo* _impl

c_foo_holder.pxd

cdef extern from "FooHolder.h":
    cdef cppclass cFooHolder:
        cFooHolder(cFoo* foo)    

foo_holder.pyx

from c_foo_holder cimport cFooHolder
from c_foo cimport cFoo

cdef class FooHolder:
    cdef cFooHolder* _impl
    def __init__(self, foo):
        self._impl = new cFooHolder(<cFoo*>(foo._impl)) # error here    

但在最后一行我收到错误“Python 对象不能转换为原始类型的指针”。我还尝试了其他几种方法,但没有任何效果:

# error: 'Foo' is not a type identifier 
from foo import Foo
def __init__(self, Foo foo):
    self._impl = new cFooHolder(foo._impl)

# error: 'Foo' is not a type identifier 
def __init__(self, foo):
   self._impl = new cFooHolder(<Foo>(foo)._impl)

【问题讨论】:

    标签: cython


    【解决方案1】:

    我找到了解决方案。您必须告诉 cython foo._impl 确实是 cFoo* 实例。这可以通过提供 Foo 定义来实现(例如在 foo.pxd 中)。之后,您可以将 python 对象转换为 Foo 并且 cython 将知道其 _impl 字段的类型为 cFoo*。

    foo.pxd

    from c_foo cimport cFoo
    cdef class Foo:
        cdef cFoo* _impl
    

    foo.pyx

    from c_foo cimport cFoo
    cdef class Foo:
        # methods implementation
    

    c_foo_holder.pxd

    cdef extern from "FooHolder.h":
        cdef cppclass cFooHolder:
            cFooHolder(cFoo* foo)    
    

    foo_holder.pyx

    from c_foo_holder cimport cFooHolder
    from c_foo cimport cFoo
    from foo cimport Foo
    
    cdef class FooHolder:
        cdef cFooHolder* _impl
        def __init__(self, foo):
            self._impl = new cFooHolder((<Foo?>foo)._impl)  
    

    【讨论】:

      【解决方案2】:

      __init__构造函数只能接受纯python对象,也有__cinit__但只能接受C原始类型。

      当您将 Foo 传递给 __init__ 时,它看不到 _impl 成员,只能看到 python 类型的成员。

      解决方案是将cFoo* 显式传递给模拟构造函数的Init() 方法:

      cdef class FooHolder:
          cdef cFooHolder* _impl
          cdef void Init(self, cFoo* foo_impl):
              self._impl = new cFooHolder(foo_impl)
      

      这样称呼:

      fooHolder = new FooHolder()
      fooHolder.Init(foo._impl)
      

      【讨论】:

      • 似乎,当 foo 是 python 对象时,我也不能这样做。我错过了什么吗?如果我用'def'定义函数,我会得到'无法将Python对象参数转换为'cFoo *'类型,如果我用'cdef'定义它,我不能从python调用它。
      • @DikobrAz 嗯好像不能在类外调用cdef方法,尝试通过全局函数而不是Init()方法设置类成员,看这个例子:stackoverflow.com/a/12205374/623622跨度>
      • 不走运。据我所知,我根本无法从 python 调用 cdef 成员,它们只能在 cython 模块中访问。而且我不能(不知道如何)将 python 对象转换为 cython 指针,所以这实际上是问题所在。
      • @DikobrAz 你不能从 python 调用 cdef 函数。
      猜你喜欢
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 2013-06-05
      • 1970-01-01
      • 2020-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多