2012-08-30 132 views
19
cdef extern from "Foo.h": 
    cdef cppclass Bar: 
     pass 

cdef class PyClass: 
    cdef Bar *bar 

    def __cinit__(self, Bar *b) 
     bar = b 

这将始终给我的东西,如:
Cannot convert Python object argument to type 'Bar *'传C++指针作为参数转换为用Cython功能

有没有做到这一点的方式,或者我需要提取一切从Bar对象,创建一个Python等价物,传入它,然后在PyClass重建它?

回答

5

对于每个CDEF类创建充当构造全局CDEF功能,CefResponse是一个C++对象,PyResponse一个python等效C++对象的:

cdef object CreatePyResponse(CefRefPtr[CefResponse] cefResponse): 

    pyResponse = PyResponse() 
    pyResponse.cefResponse = cefResponse 
    return pyResponse 

cdef class PyResponse: 

    cdef CefRefPtr[CefResponse] cefResponse 

    def GetStatus(self): 

     return (<CefResponse*>(self.cefResponse.get())).GetStatus() 

所以不是resp = PyResponse(cppObject)呼叫resp = CreatePyResponse(cppObject)

实施例从CEF的Python采取: https://code.google.com/p/cefpython/source/browse/cefpython/response.pyx?r=0250b65e046a

2

Python类接受的Python参数。要通过你需要用它一个C++的说法:

# distutils: language = c++ 

cdef extern from "Foo.h" namespace "baz": 
    cdef cppclass Bar: 
     Bar(double d) 
     double get() 

cdef class PyBar: # wrap Bar class 
    cdef Bar *thisptr 
    def __cinit__(self, double d): 
     self.thisptr = new Bar(d) 
    def __dealloc__(self): 
     del self.thisptr 
    property d: 
     def __get__(self): 
      return self.thisptr.get() 

PyBar情况下,可以使用任何其他Python对象无论从用Cython和纯Python:

class PyClass: 
    def __init__(self, PyBar bar): 
     self.bar = bar 

print(PyClass(PyBar(1)).bar.d) 
9

我碰到这个问题来试图总结C代码结构为python类。这个问题似乎是“特殊”功能,包括__init____cinit__必须声明为def而不是cdef。这意味着它们可以从普通的python中调用,所以类型参数被有效地忽略,所有东西都被当作对象。

在J.F. Sebastian的回答中,修复不是包装 - double是一个基本的数字类型,因此C/C++类型和Python对象之间存在默认转换。 Czarek的答案基本上是正确的 - 你需要使用一个伪造的构造函数,使用全局函数。无法使用@staticmethod装饰器,因为它们不能应用于cdef函数。答案在提供的原始示例中看起来更简单。

cdef extern from "Foo.h": 
    cdef cppclass Bar: 
     pass 

cdef class PyClass: 
    cdef Bar *bar 

cdef PyClass_Init(Bar *b): 
    result = PyClass() 
    result.bar = b 
    return result 
+3

在最近的版本用Cy​​thon的(如0.22至少),该@staticmethod装饰可以在CDEF功能应用,让一个现在可以在全球创造者功能转换为一个适合整洁组织的静态类。 – Dologan

+0

'bar' C++类不是基本的数字类型,并且没有默认转换。 – jfs

+0

@ J.F.Sebastian你能解释一下你的意思吗?为了存储指向它的指针,Bar不必是基本的数字类型。 – Amoss

6

由于Cython 0.21已经可以宣布cdef方法与@staticmethod装饰。这使得采取非Python的参数静态创作者的方法:

cdef extern from "Foo.h": 
    cdef cppclass Bar: 
     pass 

cdef class PyClass: 
    cdef Bar *bar 

    @staticmethod 
    cdef create(Bar *bar): 
     cdef PyClass pc = PyClass() 
     pc.bar = bar 
     return pc