diff options
-rw-r--r-- | common/pybindings.h | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/common/pybindings.h b/common/pybindings.h index 84280908..5b2adc6a 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -76,6 +76,54 @@ struct range_wrapper { } }; +/* +A wrapper to enable custom type/ID to/from string conversions + */ +template <typename T> struct string_wrapper { + template<typename F> + struct from_pystring_converter { + from_pystring_converter() { + converter::registry::push_back( + &convertible, + &construct, + boost::python::type_id<T>()); + }; + + static void* convertible(PyObject* object) { + return PyUnicode_Check(object) ? object : 0; + } + + static void construct( + PyObject* object, + converter::rvalue_from_python_stage1_data* data) { + const wchar_t* value = PyUnicode_AsUnicode(object); + const std::wstring value_ws(value); + if (value == 0) throw_error_already_set(); + void* storage = ( + (boost::python::converter::rvalue_from_python_storage<T>*) + data)->storage.bytes; + new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + data->convertible = storage; + } + + static F fn; + }; + + template<typename F> struct to_str_wrapper { + static F fn; + std::string str(T& x) { + return fn(x); + } + }; + + template<typename F1, typename F2> static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { + from_pystring_converter<F2>::fn = from_str_fn; + from_pystring_converter<F2>(); + to_str_wrapper<F1>::fn = to_str_fn; + class_<T>(type_name, no_init).def("__str__", to_str_wrapper<F1>::str); + }; +}; + #define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator") void init_python(const char *executable); |