2011-06-08 102 views
17

所以,我想創建一個to_python轉換器,它將允許我從一個公開的函數返回一個boost :: optional,並將它視爲T如果設置了可選項如果沒有則爲無。根據我在C++Sig上發現的帖子,我編寫了下面的代碼。Boost Python沒有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>(); 
    } 
}; 

據我所知道的,它適用於轉換自選,但蟒蛇拋出以下異常「類型錯誤:沒有to_python(按值)發現C++的類型轉換器:的std :: string」。我知道C++能夠將字符串轉換爲python,因爲大多數我公開的函數都會返回字符串。爲什麼boost :: 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

請將您的解決方案的答案和接受它。 – 2011-06-29 00:22:30

回答

4

好的,這裏是整個和來自可選的轉換器基於原始的C + +簽署職位,但重寫使用高級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(「shortest」,&automaton :: shortest,(arg(「num」)= boost :: none))'聲明可選參數默認值('short',&automaton :: shortest,(arg(「num」)= boost ::可選()))''。你碰巧知道缺少對'boost :: none'的支持嗎? – akim 2015-04-10 15:54:00

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 
    ); 
    } 
    } 
}; 
相關問題