2012-08-30 169 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