2011-06-08 15 views
17

के लिए मिला है, इसलिए, मैं एक to_python कनवर्टर बनाने की कोशिश कर रहा हूं जो मुझे एक उजागर समारोह से एक बढ़ावा :: वैकल्पिक वापस करने की अनुमति देगा और वैकल्पिक सेट होने पर इसे टी के रूप में माना जाएगा और यदि नहीं तो कोई नहीं। C++Sig पर मिली एक पोस्ट के आधार पर, मैंने निम्नलिखित कोड लिखा था।बूस्ट पायथन कोई to_python कनवर्टर std :: string

template<typename T> 
struct optional_ : private boost::noncopyable { 
    struct conversion { 
    static PyObject* convert(boost::optional<T> const& value) { 
     if (value) { 
     return boost::python::to_python_value<T>()(*value); 
     } 
     Py_INCREF(Py_None); 
     return Py_None; 
    } 
    }; 
    explicit optional_() { 
    boost::python::to_python_converter<boost::optional<T>, conversion>(); 
    } 
}; 

जहां तक ​​मेरा बता सकते हैं, यह optionals परिवर्तित करने के लिए काम करता है, लेकिन अजगर फेंकता निम्नलिखित अपवाद "लेखन त्रुटि: कोई to_python (दर-मूल्य) सी ++ प्रकार के लिए पाया कनवर्टर: std :: स्ट्रिंग"। मुझे पता है कि सी ++ स्ट्रिंग्स को पायथन में कनवर्ट करने में सक्षम है क्योंकि मेरे अधिकांश खुला फ़ंक्शन स्ट्रिंग लौटते हैं। क्यों बढ़ावा नहीं देता :: python :: to_python_value इसे पहचानता है, और मैं इसके कनवर्टर का उपयोग कैसे कर सकता हूं?

निम्नलिखित (पर this article आधार पर) के लिए बदलने के द्वारा निश्चित:

template<typename T> 
struct optional_ : private boost::noncopyable { 
    struct conversion { 
    static PyObject* convert(boost::optional<T> const& value) { 
     using namespace boost::python; 
     return incref((value ? object(*value) : object()).ptr()); 
    } 
    }; 
    explicit optional_() { 
    boost::python::to_python_converter<boost::optional<T>, conversion>(); 
    } 
}; 

अब दूसरे संस्करण इतना है कि यह क्लीनर है और बेहतर काम करता है बस क्या करना है।

+9

कृपया एक उत्तर के लिए अपने समाधान के लिए कदम है और यह स्वीकार करते हैं। –

उत्तर

4

ठीक है यहां मूल सी ++ सिग पोस्ट के आधार पर वैकल्पिक कनवर्टर से और संपूर्ण है, लेकिन उच्च स्तरीय boost.python API (अजीब दूरी के बारे में खेद है) का उपयोग करने के लिए फिर से लिखा गया है।

template<typename T> 
struct optional_ : private boost::noncopyable 
{ 
    struct conversion : 
    public boost::python::converter::expected_from_python_type<T> 
    { 
    static PyObject* convert(boost::optional<T> const& value) { 
     using namespace boost::python; 
     return incref((value ? object(*value) : object()).ptr()); 
    } 
    }; 

    static void* convertible(PyObject *obj) { 
    using namespace boost::python; 
    return obj == Py_None || extract<T>(obj).check() ? obj : NULL; 
    } 

    static void constructor(PyObject *obj, 
     boost::python::converter::rvalue_from_python_stage1_data *data) 
    { 
    using namespace boost::python; 
    void *const storage = 
     reinterpret_cast< 
     converter::rvalue_from_python_storage<boost::optional<T> >* 
     >(data)->storage.bytes; 
    if(obj == Py_None) { 
     new (storage) boost::optional<T>(); 
    } else { 
     new (storage) boost::optional<T>(extract<T>(obj)); 
    } 
    data->convertible = storage; 
    } 

    explicit optional_() { 
    using namespace boost::python; 
    if(!extract<boost::optional<T> >(object()).check()) { 
     to_python_converter<boost::optional<T>, conversion, true>(); 
     converter::registry::push_back(
     &convertible, 
     &constructor, 
     type_id<boost::optional<T> >(), 
     &conversion::get_pytype 
    ); 
    } 
    } 
}; 
+0

यह महान काम करता है, बहुत बहुत धन्यवाद! हालांकि, कुछ गायब होना चाहिए: मैं '[...]। Def (" सबसे छोटा ", और automaton :: सबसे छोटा, (arg (" num ") = boost :: none) का उपयोग नहीं कर सकता) 'वैकल्पिक तर्कों को डिफ़ॉल्ट घोषित करने के लिए 'कोई नहीं', मुझे लिखना होगा '[...]। def ("सबसे छोटा", और automaton :: सबसे छोटा, (arg ("num") = boost :: वैकल्पिक ())) '। क्या आपको पता है कि 'बूस्ट :: कोई नहीं' के लिए समर्थन पाने के लिए क्या गुम है? – akim

0

उपरोक्त कोड में उसमें गलतियों रहे हैं - यहाँ सही संस्करण है:

#include <boost/noncopyable.hpp> 
#include <boost/optional.hpp> 
#include <boost/python.hpp> 

template<typename T> 
struct python_optional : private boost::noncopyable { 
    struct conversion : public boost::python::converter::expected_from_python_type<T> 
    { 
    static PyObject* convert(boost::optional<T> const& value) 
    { 
     using namespace boost::python; 
     return incref((value ? object(*value) : object()).ptr()); 
    } 
    }; 

    static void* convertible(PyObject *obj) { 
    using namespace boost::python; 
    return obj == Py_None || extract<T>(obj).check() ? obj : NULL; 
    } 

    static void constructor(
    PyObject *obj, 
    boost::python::converter::rvalue_from_python_stage1_data *data 
) { 
    using namespace boost::python; 
    void *const storage = 
     reinterpret_cast< 
     converter::rvalue_from_python_storage<boost::optional<T> >* 
     >(data)->storage.bytes; 
    if(obj == Py_None) { 
     new (storage) boost::optional<T>(); 
    } else { 
     new (storage) boost::optional<T>(extract<T>(obj)); 
    } 
    data->convertible = storage; 
    } 

    explicit python_optional() { 
    using namespace boost::python; 
    if(!extract<boost::optional<T> >(object()).check()) { 
     to_python_converter<boost::optional<T>, conversion, true>(); 
     converter::registry::push_back(
     &convertible, 
     &constructor, 
     type_id<boost::optional<T> >(), 
     &conversion::get_pytype 
    ); 
    } 
    } 
}; 
संबंधित मुद्दे