diff --git a/doc/news.html b/doc/news.html
index 19b00ecb..571788ae 100644
--- a/doc/news.html
+++ b/doc/news.html
@@ -31,23 +31,33 @@
- 11 Sept 2003
- - Changed the response to multiple to-python converters being
- registered for the same type from a hard error into warning;
- Boost.Python now reports the offending type in the message.
+
-
+
+ - Changed the response to multiple to-python converters being
+ registered for the same type from a hard error into warning;
+ Boost.Python now reports the offending type in the message.
+
+ - Added builtin
std::wstring conversions
+
+ - Added
std::out_of_range => Python
+ IndexError exception conversion, thanks to Raoul Gough
+
+
- 9 Sept 2003
- - Added new
str constructors
- which take a range of characters, allowing strings containing
- nul ('\0') characters.
+ - Added new
str
+
+ - constructors which take a range of characters, allowing strings
+ containing nul (
'\0') characters.
- 8 Sept 2003
- - Added the ability to create methods from function
- objects (with an
operator()); see the make_function
- docs for more info.
+ - Added the ability to create methods from function objects (with an
+
operator()); see the make_function docs for
+ more info.
- 10 August 2003
@@ -170,7 +180,8 @@ BOOST_PYTHON_MODULE(test)
Revised
- 11 September 2003
+ 11 September 2003
+
© Copyright Dave
diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp
index e78eee9a..9d780282 100644
--- a/include/boost/python/converter/builtin_converters.hpp
+++ b/include/boost/python/converter/builtin_converters.hpp
@@ -82,16 +82,16 @@ namespace detail
// Specialize converters for signed and unsigned T to Python Int
# define BOOST_PYTHON_TO_INT(T) \
- BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \
+ BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x)) \
BOOST_PYTHON_TO_PYTHON_BY_VALUE( \
unsigned T \
, static_cast(x) > static_cast( \
std::numeric_limits::max()) \
- ? PyLong_FromUnsignedLong(x) \
- : PyInt_FromLong(x))
+ ? ::PyLong_FromUnsignedLong(x) \
+ : ::PyInt_FromLong(x))
// Bool is not signed.
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, PyInt_FromLong(x))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x))
// note: handles signed char and unsigned char, but not char (see below)
BOOST_PYTHON_TO_INT(char)
@@ -103,23 +103,29 @@ BOOST_PYTHON_TO_INT(long)
// using Python's macro instead of Boost's - we don't seem to get the
// config right all the time.
# ifdef HAVE_LONG_LONG
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, PyLong_FromLongLong(x))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, PyLong_FromUnsignedLongLong(x))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x))
# endif
# undef BOOST_TO_PYTHON_INT
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromStringAndSize(x.c_str(),x.size()))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),x.size()))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),x.size()))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x))
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag()))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag()))
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, PyComplex_FromDoubles(x.real(), x.imag()))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag()))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag()))
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag()))
+# undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE
+# undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE
+# undef BOOST_PYTHON_TO_PYTHON_BY_VALUE
+# undef BOOST_PYTHON_TO_INT
+
namespace converter
{
diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp
index bd49c832..40413192 100644
--- a/src/converter/builtin_converters.cpp
+++ b/src/converter/builtin_converters.cpp
@@ -272,6 +272,42 @@ namespace
}
};
+ // encode_string_unaryfunc/py_encode_string -- manufacture a unaryfunc
+ // "slot" which encodes a Python string using the default encoding
+ extern "C" PyObject* encode_string_unaryfunc(PyObject* x)
+ {
+ return PyUnicode_FromEncodedObject( x, 0, 0 );
+ }
+ unaryfunc py_encode_string = encode_string_unaryfunc;
+
+ // A SlotPolicy for extracting C++ strings from Python objects.
+ struct wstring_rvalue_from_python
+ {
+ // If the underlying object is "string-able" this will succeed
+ static unaryfunc* get_slot(PyObject* obj)
+ {
+ return PyUnicode_Check(obj)
+ ? &py_object_identity
+ : PyString_Check(obj)
+ ? &py_encode_string
+ : 0;
+ };
+
+ // Remember that this will be used to construct the result object
+ static std::wstring extract(PyObject* intermediate)
+ {
+ std::wstring result(::PyObject_Length(intermediate), L' ');
+ int err = PyUnicode_AsWideChar(
+ (PyUnicodeObject *)intermediate
+ , result.size() ? &result[0] : 0
+ , result.size());
+
+ if (err == -1)
+ throw_error_already_set();
+ return result;
+ }
+ };
+
struct complex_rvalue_from_python
{
static unaryfunc* get_slot(PyObject* obj)
@@ -366,7 +402,8 @@ void initialize_builtin_converters()
// Add an lvalue converter for char which gets us char const*
registry::insert(convert_to_cstring,type_id());
- // Register by-value converters to std::string
+ // Register by-value converters to std::string, std::wstring
+ slot_rvalue_from_python();
slot_rvalue_from_python();
}
diff --git a/src/errors.cpp b/src/errors.cpp
index 6a23fc9a..a2ab071e 100644
--- a/src/errors.cpp
+++ b/src/errors.cpp
@@ -38,6 +38,10 @@ BOOST_PYTHON_DECL bool handle_exception_impl(function0 f)
{
PyErr_SetString(PyExc_OverflowError, x.what());
}
+ catch(const std::out_of_range& x)
+ {
+ PyErr_SetString(PyExc_IndexError, x.what());
+ }
catch(const std::exception& x)
{
PyErr_SetString(PyExc_RuntimeError, x.what());
diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp
index 6301a6d0..853ae942 100644
--- a/test/test_builtin_converters.cpp
+++ b/test/test_builtin_converters.cpp
@@ -83,6 +83,8 @@ BOOST_PYTHON_MODULE(builtin_converters)
def("rewrap_value_complex_float", by_value >::rewrap);
def("rewrap_value_complex_double", by_value >::rewrap);
def("rewrap_value_complex_long_double", by_value >::rewrap);
+ def("rewrap_value_wstring", by_value::rewrap);
+ def("rewrap_value_string", by_value::rewrap);
def("rewrap_value_string", by_value::rewrap);
def("rewrap_value_cstring", by_value::rewrap);
def("rewrap_value_handle", by_value >::rewrap);
diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py
index 1304ea32..345f2669 100644
--- a/test/test_builtin_converters.py
+++ b/test/test_builtin_converters.py
@@ -75,6 +75,13 @@ r"""
'hello, world'
>>> rewrap_value_string('yo, wassup?')
'yo, wassup?'
+>>> rewrap_value_wstring(u'yo, wassup?')
+u'yo, wassup?'
+
+ test that overloading on unicode works:
+
+>>> rewrap_value_string(u'yo, wassup?')
+u'yo, wassup?'
wrap strings with embedded nulls: