2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-23 05:42:30 +00:00

Added std::wstring conversion support

Added std::out_of_range => Python IndexError exception conversion,
thanks to Raoul Gough


[SVN r20027]
This commit is contained in:
Dave Abrahams
2003-09-11 19:19:55 +00:00
parent 8b97caae46
commit f920dc87d0
6 changed files with 93 additions and 26 deletions

View File

@@ -31,23 +31,33 @@
<dl class="page-index">
<dt>11 Sept 2003</dt>
<dd>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.
<dd>
<ul>
<li>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.</li>
<li>Added builtin <code>std::wstring</code> conversions</li>
<li>Added <code>std::out_of_range</code> =&gt; Python
<code>IndexError</code> exception conversion, thanks to <a href=
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li>
</ul>
</dd>
<dt>9 Sept 2003</dt>
<dd>Added new <code><a
href="v2/str.html#str-spec">str</a></code></dd> constructors
which take a range of characters, allowing strings containing
nul (<code>'\0'</code>) characters.
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd>
<dt>constructors which take a range of characters, allowing strings
containing nul (<code>'\0'</code>) characters.</dt>
<dt>8 Sept 2003</dt>
<dd>Added the ability to create methods from function
objects (with an <code>operator()</code>); see the <a
href="v2/make_function.html#make_function-spec">make_function</a>
docs for more info.</dd>
<dd>Added the ability to create methods from function objects (with an
<code>operator()</code>); see the <a href=
"v2/make_function.html#make_function-spec">make_function</a> docs for
more info.</dd>
<dt>10 August 2003</dt>
@@ -170,7 +180,8 @@ BOOST_PYTHON_MODULE(test)
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
11 September 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
11 September 2003
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="../../../people/dave_abrahams.htm">Dave

View File

@@ -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<unsigned long>(x) > static_cast<unsigned long>( \
std::numeric_limits<long>::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<float>, PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, ::PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::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
{

View File

@@ -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<char>());
// Register by-value converters to std::string
// Register by-value converters to std::string, std::wstring
slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>();
slot_rvalue_from_python<std::string, string_rvalue_from_python>();
}

View File

@@ -38,6 +38,10 @@ BOOST_PYTHON_DECL bool handle_exception_impl(function0<void> 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());

View File

@@ -83,6 +83,8 @@ BOOST_PYTHON_MODULE(builtin_converters)
def("rewrap_value_complex_float", by_value<std::complex<float> >::rewrap);
def("rewrap_value_complex_double", by_value<std::complex<double> >::rewrap);
def("rewrap_value_complex_long_double", by_value<std::complex<long double> >::rewrap);
def("rewrap_value_wstring", by_value<std::wstring>::rewrap);
def("rewrap_value_string", by_value<std::wstring>::rewrap);
def("rewrap_value_string", by_value<std::string>::rewrap);
def("rewrap_value_cstring", by_value<char const*>::rewrap);
def("rewrap_value_handle", by_value<handle<> >::rewrap);

View File

@@ -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: