00001 #ifndef BOOST_ADAPTBX_OPTIONAL_CONVERSIONS_H
00002 #define BOOST_ADAPTBX_OPTIONAL_CONVERSIONS_H
00003
00004 #include <boost/python/to_python_converter.hpp>
00005 #include <boost/python/extract.hpp>
00006 #include <boost/optional.hpp>
00007
00008 namespace boost_adaptbx { namespace optional_conversions {
00009
00010 namespace detail {
00011
00012 template <typename T>
00013 struct to_python
00014 {
00015 static PyObject*
00016 convert(
00017 boost::optional<T> const& value)
00018 {
00019 if (value) {
00020 return boost::python::incref(boost::python::object(*value).ptr());
00021 }
00022 return boost::python::incref(Py_None);
00023 }
00024
00025 static const PyTypeObject* get_pytype()
00026 {
00027 return boost::python::converter::registered<T>::converters
00028 .to_python_target_type();
00029 }
00030 };
00031
00032 }
00033
00034 template <typename T>
00035 struct to_python
00036 {
00037 to_python()
00038 {
00039 boost::python::to_python_converter<
00040 boost::optional<T>,
00041 detail::to_python<T>
00042 #ifdef BOOST_PYTHON_SUPPORTS_PY_SIGNATURES
00043 , true
00044 #endif
00045 >();
00046 }
00047 };
00048
00049 template <typename T>
00050 struct from_python
00051 {
00052 from_python()
00053 {
00054 boost::python::converter::registry::push_back(
00055 &convertible,
00056 &construct,
00057 boost::python::type_id<boost::optional<T> >()
00058 #ifdef BOOST_PYTHON_SUPPORTS_PY_SIGNATURES
00059 , &boost::python::converter::expected_pytype_for_arg<T>::get_pytype
00060 #endif
00061 );
00062 }
00063
00064 static void* convertible(PyObject* obj_ptr)
00065 {
00066 if (obj_ptr != Py_None) {
00067 boost::python::extract<T> proxy(obj_ptr);
00068 if (!proxy.check()) return 0;
00069 }
00070 return obj_ptr;
00071 }
00072
00073 static void construct(
00074 PyObject* obj_ptr,
00075 boost::python::converter::rvalue_from_python_stage1_data* data)
00076 {
00077 boost::optional<T> value;
00078 if (obj_ptr != Py_None) {
00079 boost::python::extract<T> proxy(obj_ptr);
00080 value.reset(proxy());
00081 }
00082 void* storage = (
00083 (boost::python::converter::rvalue_from_python_storage<
00084 boost::optional<T> >*)
00085 data)->storage.bytes;
00086 new (storage) boost::optional<T>(value);
00087 data->convertible = storage;
00088 }
00089 };
00090
00091 template <typename T>
00092 struct to_and_from_python
00093 {
00094 to_and_from_python()
00095 {
00096 to_python<T>();
00097 from_python<T>();
00098 }
00099 };
00100
00101 }}
00102
00103 #endif // BOOST_ADAPTBX_OPTIONAL_CONVERSIONS_H