Skip to content

Commit 56e7b2a

Browse files
committed
* object(f), where f is a function pointer now works. Returning a
* function pointer from a function should work also. * make_function/make_constructor now return object instead of a raw pointer. * module::setattr() now accepts anything which can be passed to object's constructor. * Rework upcast<> to catch more errors at compile-time instead of infinite-looping. * Rationalize class<>::def() in preparation for docstring support * Partial docstring support in module::def (untested) * dependent<> trick moved to detail namespace and separate header * Added __doc__ attribute to C++ function wrapper objects * Sunk implementation of function_object into a library source file. [SVN r14724]
1 parent 61d0307 commit 56e7b2a

25 files changed

+401
-231
lines changed

include/boost/python/back_reference.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,24 @@
77
# define BACK_REFERENCE_DWA2002510_HPP
88

99
# include <boost/python/handle.hpp>
10-
# include <boost/python/object_core.hpp>
10+
# include <boost/python/object_fwd.hpp>
11+
# include <boost/python/detail/dependent.hpp>
1112

1213
namespace boost { namespace python {
1314

1415
template <class T>
1516
struct back_reference
1617
{
18+
private: // types
19+
typedef typename detail::dependent<object,T>::type source_t;
1720
public:
1821
typedef T type;
1922

2023
back_reference(PyObject*, T);
21-
object const& source() const;
24+
source_t const& source() const;
2225
T get() const;
2326
private:
24-
object m_source;
27+
source_t m_source;
2528
T m_value;
2629
};
2730

@@ -82,7 +85,7 @@ back_reference<T>::back_reference(PyObject* p, T x)
8285
}
8386

8487
template <class T>
85-
object const& back_reference<T>::source() const
88+
typename back_reference<T>::source_t const& back_reference<T>::source() const
8689
{
8790
return m_source;
8891
}

include/boost/python/cast.hpp

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
# include <boost/python/detail/wrap_python.hpp>
1010
# include <boost/type_traits/same_traits.hpp>
11+
# include <boost/type_traits/cv_traits.hpp>
1112
# include <boost/type.hpp>
1213
# include <boost/python/base_type_traits.hpp>
1314
# include <boost/python/detail/convertible.hpp>
@@ -16,19 +17,42 @@ namespace boost { namespace python {
1617

1718
namespace detail
1819
{
19-
template <class Target>
20-
inline Target* upcast(Target* p, yes_convertible)
20+
template <class Source, class Target> inline Target* upcast_impl(Source*, Target*);
21+
22+
template <class Source, class Target>
23+
inline Target* upcast(Source* p, yes_convertible, no_convertible, Target*)
2124
{
2225
return p;
2326
}
2427

25-
template <class Target, class Source>
26-
inline Target* upcast(Source* p, no_convertible, boost::type<Target>* = 0)
28+
template <class Source, class Target>
29+
inline Target* upcast(Source* p, no_convertible, no_convertible, Target*)
2730
{
2831
typedef typename base_type_traits<Source>::type base;
29-
return detail::upcast<Target>((base*)p, convertible<Target*>::check((base*)0));
32+
33+
return detail::upcast_impl((base*)p, (Target*)0);
3034
}
3135

36+
template <bool is_same = true>
37+
struct upcaster
38+
{
39+
template <class T>
40+
static inline T* execute(T* x, T*) { return x; }
41+
};
42+
43+
template <>
44+
struct upcaster<false>
45+
{
46+
template <class Source, class Target>
47+
static inline Target* execute(Source* x, Target*)
48+
{
49+
return detail::upcast(
50+
x, detail::convertible<Target*>::check(x)
51+
, detail::convertible<Source*>::check((Target*)0)
52+
, (Target*)0);
53+
}
54+
};
55+
3256

3357
template <class Target, class Source>
3458
inline Target* downcast(Source* p, yes_convertible)
@@ -48,14 +72,25 @@ namespace detail
4872
{
4973
typedef char must_be_a_complete_type[sizeof(T)];
5074
}
75+
76+
template <class Source, class Target>
77+
inline Target* upcast_impl(Source* x, Target*)
78+
{
79+
typedef typename add_cv<Source>::type src_t;
80+
typedef typename add_cv<Target>::type target_t;
81+
static bool const same = is_same<src_t,target_t>::value;
82+
83+
return detail::upcaster<same>::execute(x, (Target*)0);
84+
}
5185
}
5286

5387
template <class Target, class Source>
5488
inline Target* upcast(Source* x, Target* = 0)
5589
{
5690
detail::assert_castable<Source>();
5791
detail::assert_castable<Target>();
58-
return detail::upcast<Target>(x, detail::convertible<Target*>::check(x));
92+
return detail::upcast_impl(x, (Target*)0);
93+
5994
}
6095

6196
template <class Target, class Source>

include/boost/python/class.hpp

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# include <boost/python/handle.hpp>
1313
# include <boost/python/object/class.hpp>
1414
# include <boost/python/type_id.hpp>
15-
# include <boost/python/detail/wrap_function.hpp>
1615
# include <boost/python/detail/member_function_cast.hpp>
1716
# include <boost/python/object/class_converters.hpp>
1817
# include <boost/type_traits/ice.hpp>
@@ -26,6 +25,8 @@
2625
# include <boost/utility.hpp>
2726
# include <boost/python/detail/operator_id.hpp>
2827
# include <boost/python/object/pickle_support.hpp>
28+
# include <boost/python/make_function.hpp>
29+
# include <boost/python/object/add_to_namespace.hpp>
2930

3031
namespace boost { namespace python {
3132

@@ -101,30 +102,19 @@ class class_ : public objects::class_base
101102
template <class F>
102103
self& def(char const* name, F f)
103104
{
104-
// Use function::add_to_namespace to achieve overloading if
105-
// appropriate.
106-
objects::function::add_to_namespace(
107-
*this, name
108-
, object(
109-
detail::new_reference(
110-
detail::wrap_function(
111-
// This bit of nastiness casts F to a member function of T if possible.
112-
detail::member_function_cast<T,F>::stage1(f).stage2((T*)0).stage3(f)
113-
))));
105+
this->def_impl(name, f, 0, &f);
114106
return *this;
115107
}
116108

117109
template <class Fn, class CallPolicy>
118110
self& def(char const* name, Fn fn, CallPolicy policy)
119111
{
120-
this->def(name
112+
return this->def(name
121113
, boost::python::make_function(
122114
// This bit of nastiness casts F to a member function of T if possible.
123115
detail::member_function_cast<T,Fn>::stage1(fn).stage2((T*)0).stage3(fn)
124116
, policy)
125117
);
126-
127-
return *this;
128118
}
129119

130120
template <detail::operator_id id, class L, class R>
@@ -133,39 +123,32 @@ class class_ : public objects::class_base
133123
typedef detail::operator_<id,L,R> op_t;
134124
// Use function::add_to_namespace to achieve overloading if
135125
// appropriate.
136-
objects::function::add_to_namespace(
137-
*this, op.name()
138-
, object(
139-
detail::new_reference(
140-
detail::wrap_function(&op_t::template apply<T>::execute))));
141-
return *this;
126+
return this->def(op.name(), &op_t::template apply<T>::execute);
142127
}
143128

144129
// Define the constructor with the given Args, which should be an
145130
// MPL sequence of types.
146131
template <class Args>
147132
self& def_init(Args const&)
148133
{
149-
def("__init__",
150-
make_constructor<Args>(
134+
return this->def("__init__",
135+
python::make_constructor<Args>(
151136
// Using runtime type selection works around a CWPro7 bug.
152137
objects::select_holder<T,held_type>((held_type*)0).get()
153138
)
154139
);
155-
return *this;
156140
}
157141

158142
template <class Args, class CallPolicy>
159143
self& def_init(Args const&, CallPolicy policy)
160144
{
161-
def("__init__",
162-
make_constructor<Args>(
145+
return this->def("__init__",
146+
python::make_constructor<Args>(
163147
policy
164148
// Using runtime type selection works around a CWPro7 bug.
165149
, objects::select_holder<T,held_type>((held_type*)0).get()
166150
)
167151
);
168-
return *this;
169152
}
170153

171154
// Define the default constructor.
@@ -216,6 +199,24 @@ class class_ : public objects::class_base
216199
return *this;
217200
}
218201

202+
private: // helper functions
203+
204+
template <class F>
205+
inline void def_impl(char const* name, F const& f, char const* doc, ...)
206+
{
207+
objects::add_to_namespace(
208+
*this, name, make_function(
209+
// This bit of nastiness casts F to a member function of T if possible.
210+
detail::member_function_cast<T,F>::stage1(f).stage2((T*)0).stage3(f))
211+
, doc);
212+
}
213+
214+
template <class F>
215+
inline void def_impl(char const* name, F const& f, char const* doc, object const volatile*)
216+
{
217+
objects::add_to_namespace(*this, name, f, doc);
218+
}
219+
219220
private: // types
220221
typedef objects::class_id class_id;
221222

include/boost/python/converter/arg_to_python.hpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,29 @@
1313
# include <boost/python/converter/object_manager.hpp>
1414
# include <boost/python/to_python_indirect.hpp>
1515
# include <boost/type_traits/cv_traits.hpp>
16+
# include <boost/type_traits/composite_traits.hpp>
17+
# include <boost/type_traits/function_traits.hpp>
18+
# include <boost/python/detail/indirect_traits.hpp>
1619
# include <boost/python/detail/convertible.hpp>
1720
# include <boost/python/detail/string_literal.hpp>
1821
# include <boost/python/base_type_traits.hpp>
1922
// Bring in specializations
2023
# include <boost/python/converter/builtin_converters.hpp>
2124
# include <boost/python/tag.hpp>
25+
# include <boost/python/object/function_handle.hpp>
2226

2327
namespace boost { namespace python { namespace converter {
2428

2529
namespace detail
2630
{
2731
BOOST_PYTHON_DECL void throw_no_class_registered();
2832

33+
template <class T>
34+
struct function_arg_to_python : handle<>
35+
{
36+
function_arg_to_python(T const& x);
37+
};
38+
2939
template <class T>
3040
struct reference_arg_to_python : handle<>
3141
{
@@ -80,6 +90,9 @@ namespace detail
8090
BOOST_STATIC_CONSTANT(
8191
bool, is_string = python::detail::is_string_literal<T const>::value);
8292

93+
BOOST_STATIC_CONSTANT(
94+
bool, function = is_function<T>::value | python::detail::is_pointer_to_function<T>::value | is_member_function_pointer<T>::value);
95+
8396
BOOST_STATIC_CONSTANT(
8497
bool, manager = is_object_manager<T>::value);
8598

@@ -99,18 +112,22 @@ namespace detail
99112
is_string
100113
, arg_to_python<char const*>
101114
, typename mpl::select_type<
102-
manager
103-
, object_manager_arg_to_python<T>
115+
function
116+
, function_arg_to_python<T>
104117
, typename mpl::select_type<
105-
ptr
106-
, pointer_deep_arg_to_python<T>
118+
manager
119+
, object_manager_arg_to_python<T>
107120
, typename mpl::select_type<
108-
ptr_wrapper
109-
, pointer_shallow_arg_to_python<unwrapped_ptr>
121+
ptr
122+
, pointer_deep_arg_to_python<T>
110123
, typename mpl::select_type<
111-
ref_wrapper
112-
, reference_arg_to_python<unwrapped_referent>
113-
, value_arg_to_python<T>
124+
ptr_wrapper
125+
, pointer_shallow_arg_to_python<unwrapped_ptr>
126+
, typename mpl::select_type<
127+
ref_wrapper
128+
, reference_arg_to_python<unwrapped_referent>
129+
, value_arg_to_python<T>
130+
>::type
114131
>::type
115132
>::type
116133
>::type
@@ -168,6 +185,12 @@ namespace detail
168185
}
169186
// ---------
170187

188+
template <class T>
189+
inline function_arg_to_python<T>::function_arg_to_python(T const& x)
190+
: handle<>(python::objects::make_function_handle(x))
191+
{
192+
}
193+
171194
template <class T>
172195
inline value_arg_to_python<T>::value_arg_to_python(T const& x)
173196
: arg_to_python_base(&x, registered<T>::converters)

include/boost/python/data_members.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88

99
# include <boost/python/detail/config.hpp>
1010
# include <boost/python/detail/wrap_python.hpp>
11-
# include <boost/python/object/function.hpp>
1211
# include <boost/type_traits/transform_traits.hpp>
1312
# include <boost/type_traits/cv_traits.hpp>
1413
# include <boost/python/return_value_policy.hpp>
1514
# include <boost/python/copy_non_const_reference.hpp>
1615
# include <boost/python/object/function_object.hpp>
16+
# include <boost/python/arg_from_python.hpp>
17+
# include <boost/bind.hpp>
1718

1819
namespace boost { namespace python {
1920

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
#ifndef DEPENDENT_DWA200286_HPP
7+
# define DEPENDENT_DWA200286_HPP
8+
9+
namespace boost { namespace python { namespace detail {
10+
11+
// A way to turn a concrete type T into a type dependent on U. This
12+
// keeps conforming compilers (those implementing proper 2-phase
13+
// name lookup for templates) from complaining about incomplete
14+
// types in situations where it would otherwise be inconvenient or
15+
// impossible to re-order code so that all types are defined in time.
16+
17+
// One such use is when we must return an incomplete T from a member
18+
// function template (which must be defined in the class body to
19+
// keep MSVC happy).
20+
template <class T, class U>
21+
struct dependent
22+
{
23+
typedef T type;
24+
};
25+
26+
}}} // namespace boost::python::detail
27+
28+
#endif // DEPENDENT_DWA200286_HPP

include/boost/python/detail/module_base.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# define MODULE_BASE_DWA2002227_HPP
88
# include <boost/python/detail/wrap_python.hpp>
99
# include <boost/python/handle.hpp>
10+
# include <boost/python/object_fwd.hpp>
1011

1112
namespace boost { namespace python { namespace detail {
1213

@@ -18,14 +19,13 @@ class BOOST_PYTHON_DECL module_base
1819
~module_base();
1920

2021
// Add elements to the module
21-
void setattr(const char* name, PyObject*);
22-
void setattr(const char* name, handle<> const&);
2322
void add(type_handle const&); // just use the type's name
2423

2524
// Return a reference to the Python module object being built
2625
inline handle<> object() const;
2726

2827
protected:
28+
void setattr_doc(const char* name, python::object const&, char const* doc);
2929
void add_class(type_handle const& class_obj);
3030

3131
private:

0 commit comments

Comments
 (0)