Skip to content

Commit 0e76fcf

Browse files
committed
auto_ptr support
[SVN r16228]
1 parent 6b4dc29 commit 0e76fcf

13 files changed

+225
-23
lines changed

include/boost/python/converter/arg_from_python.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ template <class T>
103103
struct arg_rvalue_from_python
104104
{
105105
typedef typename boost::add_reference<
106-
typename boost::add_const<T>::type
106+
T
107+
// We can't add_const here, or it would be impossible to pass
108+
// auto_ptr<U> args from Python to C++
107109
>::type result_type;
108110

109111
arg_rvalue_from_python(PyObject*);

include/boost/python/converter/arg_to_python_base.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// to its suitability for any purpose.
66
#ifndef ARG_TO_PYTHON_BASE_DWA200237_HPP
77
# define ARG_TO_PYTHON_BASE_DWA200237_HPP
8-
# include <boost/python/converter/to_python_function_type.hpp>
98
# include <boost/python/detail/wrap_python.hpp>
109
# include <boost/python/handle.hpp>
1110

include/boost/python/converter/return_from_python.hpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
# include <boost/python/converter/registered.hpp>
1212
# include <boost/python/converter/registered_pointee.hpp>
1313
# include <boost/python/detail/void_ptr.hpp>
14-
# include <boost/call_traits.hpp>
1514
# include <boost/python/detail/void_return.hpp>
1615
# include <boost/python/errors.hpp>
16+
# include <boost/type_traits/has_trivial_copy.hpp>
17+
# include <boost/mpl/logical/and.hpp>
18+
# include <boost/mpl/bool_c.hpp>
1719

1820
namespace boost { namespace python { namespace converter {
1921

@@ -38,7 +40,14 @@ namespace detail
3840
template <class T>
3941
struct return_rvalue_from_python
4042
{
41-
typedef typename call_traits<T>::param_type result_type;
43+
typedef typename mpl::if_<
44+
mpl::logical_and<
45+
has_trivial_copy<T>, mpl::bool_c<(sizeof(T) <= 2 * sizeof(double))>
46+
>
47+
, T
48+
, T&
49+
>::type result_type;
50+
4251
return_rvalue_from_python();
4352
result_type operator()(PyObject*);
4453
private:

include/boost/python/converter/to_python_function_type.hpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
77
# define TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
88
# include <boost/python/detail/wrap_python.hpp>
9+
# include <boost/static_assert.hpp>
910

1011
namespace boost { namespace python { namespace converter {
1112

@@ -19,9 +20,35 @@ typedef PyObject* (*to_python_function_t)(void const*);
1920
template <class T, class ToPython>
2021
struct as_to_python_function
2122
{
23+
// Assertion functions used to prevent wrapping of converters
24+
// which take non-const reference parameters. The T* argument in
25+
// the first overload ensures it isn't used in case T is a
26+
// reference.
27+
template <class U>
28+
static int convert_function_must_take_value_or_const_reference(U(*)(T), int, T* = 0);
29+
template <class U>
30+
static int convert_function_must_take_value_or_const_reference(U(*)(T const&), long ...);
31+
2232
static PyObject* convert(void const* x)
2333
{
24-
return ToPython::convert(*(T const*)x);
34+
35+
BOOST_STATIC_ASSERT(
36+
sizeof(
37+
convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L))
38+
== sizeof(int));
39+
40+
// Yes, the const_cast below opens a hole in const-correctness,
41+
// but it's needed to convert auto_ptr<U> to python.
42+
//
43+
// How big a hole is it? It allows ToPython::convert() to be
44+
// a function which modifies its argument. The upshot is that
45+
// client converters applied to const objects may invoke
46+
// undefined behavior. The damage, however, is limited by the
47+
// use of the assertion function. Thus, the only way this can
48+
// modify its argument is if T is an auto_ptr-like type. There
49+
// is still a const-correctness hole w.r.t. auto_ptr<U> const,
50+
// but c'est la vie.
51+
return ToPython::convert(*const_cast<T*>(static_cast<T const*>(x)));
2552
}
2653
};
2754

include/boost/python/object/class_converters.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
#ifndef CLASS_CONVERTERS_DWA2002119_HPP
77
# define CLASS_CONVERTERS_DWA2002119_HPP
88

9-
# include <boost/python/object/class_wrapper.hpp>
109
# include <boost/mpl/for_each.hpp>
11-
# include <boost/python/handle.hpp>
1210
# include <boost/python/converter/registry.hpp>
1311
# include <boost/python/object/find_instance.hpp>
1412
# include <boost/python/object/inheritance.hpp>

include/boost/python/object/class_wrapper.hpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,27 @@ namespace boost { namespace python { namespace objects {
1313

1414
// Used to convert objects of type Src to wrapped C++ classes by
1515
// building a new instance object and installing a Holder constructed
16-
// from the Src object.
16+
// from a Src const&.
1717
template <class Src, class Holder, class MakeInstance>
1818
struct class_wrapper
1919
: to_python_converter<Src,class_wrapper<Src,Holder,MakeInstance> >
2020
{
2121
static PyObject* convert(Src const& x)
2222
{
23-
return MakeInstance::execute(cref(x));
23+
return MakeInstance::execute(boost::ref(x));
24+
}
25+
};
26+
27+
// Used to convert objects of type Src to wrapped C++ classes by
28+
// building a new instance object and installing a Holder constructed
29+
// from a Src value.
30+
template <class Src, class Holder, class MakeInstance>
31+
struct class_value_wrapper
32+
: to_python_converter<Src,class_value_wrapper<Src,Holder,MakeInstance> >
33+
{
34+
static PyObject* convert(Src x)
35+
{
36+
return MakeInstance::execute(x);
2437
}
2538
};
2639

include/boost/python/object/pointer_holder.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
# include <boost/python/object/inheritance.hpp>
1717
# include <boost/python/object/find_instance.hpp>
1818
# include <boost/python/object/forward.hpp>
19-
# include <boost/python/object/class_wrapper.hpp>
2019
# include <boost/python/pointee.hpp>
2120
# include <boost/python/detail/force_instantiate.hpp>
2221
# include <boost/python/detail/preprocessor.hpp>

include/boost/python/object/select_holder.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# include <boost/python/pointee.hpp>
1212
# include <boost/python/object/value_holder.hpp>
1313
# include <boost/python/object/pointer_holder.hpp>
14+
# include <boost/python/object/class_wrapper.hpp>
1415
# include <boost/python/object/find_instance.hpp>
1516
# include <boost/python/object/make_instance.hpp>
1617
# include <boost/python/object/instance.hpp>
@@ -97,7 +98,7 @@ namespace detail
9798
static inline void register_(mpl::bool_c<false>)
9899
{
99100
python::detail::force_instantiate(
100-
objects::class_wrapper<
101+
objects::class_value_wrapper<
101102
Ptr
102103
, type
103104
, make_instance<T,type> >());

test/Jamfile

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,19 @@ rule bpl-test ( name ? : files * : requirements * )
5555
boost-python-runtest $(name) : $(py) <pyd>$(modules) ;
5656
}
5757

58+
bpl-test auto_ptr ;
5859
bpl-test minimal ;
5960
bpl-test args ;
6061
bpl-test numpy ;
6162
bpl-test enum ;
62-
bpl-test docstring ;
6363
bpl-test exception_translator ;
6464
bpl-test pearu1 : test_cltree.py cltree.cpp ;
6565
bpl-test try : newtest.py m1.cpp m2.cpp ;
66-
bpl-test builtin_converters : test_builtin_converters.py test_builtin_converters.cpp ;
66+
67+
# Had to break this up into two files for MSVC6
68+
extension builtin_converters : test_builtin_converters.cpp test_builtin_converters2.cpp <dll>../build/boost_python ;
69+
boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters ;
70+
6771
bpl-test test_pointer_adoption ;
6872
bpl-test operators ;
6973
bpl-test callbacks ;
@@ -112,6 +116,8 @@ bpl-test pickle3 ;
112116

113117
bpl-test nested ;
114118

119+
bpl-test docstring ;
120+
115121
if $(TEST_BIENSTMAN_NON_BUGS)
116122
{
117123
bpl-test bienstman4 ;
@@ -161,11 +167,9 @@ run select_arg_to_python_test.cpp ../src/converter/type_id.cpp <lib>../../test/
161167
: $(UNIT_TEST_PROPERTIES)
162168
;
163169

164-
if $(TEST_EXPECTED_FAILURES)
165-
{
166-
compile-fail ./raw_pyobject_fail1.cpp : $(PYTHON_PROPERTIES) ;
167-
compile-fail ./raw_pyobject_fail2.cpp : $(PYTHON_PROPERTIES) ;
168-
compile-fail ./object_fail1.cpp : $(PYTHON_PROPERTIES) ;
169-
}
170+
compile-fail ./raw_pyobject_fail1.cpp : $(PYTHON_PROPERTIES) ;
171+
compile-fail ./raw_pyobject_fail2.cpp : $(PYTHON_PROPERTIES) ;
172+
compile-fail ./as_to_python_function.cpp : $(PYTHON_PROPERTIES) ;
173+
compile-fail ./object_fail1.cpp : $(PYTHON_PROPERTIES) ;
170174

171175

test/auto_ptr.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
7+
#include <boost/python/module.hpp>
8+
#include <boost/python/class.hpp>
9+
#include <boost/python/extract.hpp>
10+
#include <boost/python/def.hpp>
11+
#include "test_class.hpp"
12+
13+
#include <memory>
14+
15+
using namespace boost::python;
16+
17+
typedef test_class<> X;
18+
19+
int look(std::auto_ptr<X> const& x)
20+
{
21+
return (x.get()) ? x->value() : -1;
22+
}
23+
24+
int steal(std::auto_ptr<X> x)
25+
{
26+
return x->value();
27+
}
28+
29+
int maybe_steal(std::auto_ptr<X>& x, bool doit)
30+
{
31+
int n = x->value();
32+
if (doit)
33+
x.release();
34+
return n;
35+
}
36+
37+
std::auto_ptr<X> make()
38+
{
39+
return std::auto_ptr<X>(new X(77));
40+
}
41+
42+
std::auto_ptr<X> callback(object f)
43+
{
44+
std::auto_ptr<X> x(new X(77));
45+
// call<void>(f.ptr(),x);
46+
// return std::auto_ptr<X>(new X(77));
47+
return call<std::auto_ptr<X> >(f.ptr(), x);
48+
}
49+
50+
std::auto_ptr<X> extract_(object o)
51+
{
52+
return extract<std::auto_ptr<X> >(o);
53+
}
54+
55+
BOOST_PYTHON_MODULE(auto_ptr_ext)
56+
{
57+
class_<X, std::auto_ptr<X>, boost::noncopyable>("X", init<int>())
58+
.def("value", &X::value)
59+
;
60+
61+
def("look", look);
62+
def("steal", steal);
63+
def("maybe_steal", maybe_steal);
64+
def("make", make);
65+
def("callback", callback);
66+
def("extract", extract_);
67+
}
68+
69+
#include "module_tail.cpp"
70+

0 commit comments

Comments
 (0)