2012-08-30 27 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 *'पासिंग सी Cython समारोह

वहाँ यह पूरा करने के लिए एक रास्ता है, या मैं एक Bar वस्तु से सब-की जरूरत है, बनाने एक पाइथन समकक्ष, इसे पास करें, फिर इसे PyClass में पुनर्निर्माण करें?

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):

उत्तर

5

के लिए प्रत्येक cdef वर्ग एक वैश्विक cdef समारोह है कि एक निर्माता के रूप में कार्य बनाने के लिए, CefResponse एक सी ++ वस्तु, एक सी ++ वस्तु का एक अजगर बराबर PyResponse है।

उदाहरण CEF अजगर से लिया: https://code.google.com/p/cefpython/source/browse/cefpython/response.pyx?r=0250b65e046a

2

अजगर वर्ग अजगर तर्क स्वीकार करता है। एक सी ++ तर्क आप लपेट की जरूरत है पारित करने के लिए:

# 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 उदाहरणों वस्तुओं किसी अन्य अजगर के रूप में इस्तेमाल किया जा सकता दोनों Cython और शुद्ध अजगर से:

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

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

मैं रैप करने के लिए कोशिश कर रहा है इस समस्या में आए पाइथन कक्षाओं के रूप में structs के साथ सी कोड। ऐसा लगता है कि __init__ और __cinit__ समेत "विशेष" फ़ंक्शन cdef के बजाय def के रूप में घोषित किया जाना चाहिए। इसका मतलब है कि उन्हें सामान्य पायथन से बुलाया जा सकता है, इसलिए प्रकार के पैरामीटर प्रभावी ढंग से अनदेखा किए जाते हैं और सब कुछ वस्तु के रूप में माना जाता है।

जेएफ सेबस्टियन के जवाब में फिक्स रैपिंग नहीं है - एक डबल मूल संख्यात्मक प्रकार है और इसलिए सी/सी ++ प्रकार और पायथन ऑब्जेक्ट के बीच एक डिफ़ॉल्ट रूपांतरण है। 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

Cython के हाल के संस्करणों पर (0.22 के रूप में कम से कम), @staticmethod डेकोरेटर cdef कार्यों पर लागू किया जा सकता है ताकि एक अब वैश्विक निर्माता बना सकते हैं एक स्वच्छ वर्ग के लिए एक स्थिर वर्ग में कार्य करें। – Dologan

+0

'बार' सी ++ कक्षा मूल संख्यात्मक प्रकार नहीं है और कोई डिफ़ॉल्ट रूपांतरण नहीं है। – jfs

+0

@ जेएफ। सेबेस्टियन क्या आप समझ सकते हैं कि आपका क्या मतलब है? पॉइंटर को स्टोर करने के लिए बार को मूल संख्यात्मक प्रकार नहीं होना चाहिए। – Amoss

6

Cython 0.21 के रूप में यह @staticmethod डेकोरेटर के साथ cdef तरीकों घोषित करने के लिए संभव हो गया है। यह स्थिर निर्माता तरीकों कि गैर अजगर तर्क ले अनुमति देता है:

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 
संबंधित मुद्दे