Skip to content

Commit 865ef2a

Browse files
committed
Support for free-function def() invocation (no module object)
Fix bugs relying on initialization of objects in the Python DLL [SVN r15139]
1 parent 7d35ed4 commit 865ef2a

37 files changed

+421
-347
lines changed

include/boost/python/detail/defaults_def.hpp

Lines changed: 77 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,76 @@
1818
#include <boost/static_assert.hpp>
1919
#include <boost/preprocessor/iterate.hpp>
2020
#include <boost/python/detail/type_list_utils.hpp>
21+
#include <boost/python/class_fwd.hpp>
22+
#include <boost/python/object/function.hpp>
23+
#include <boost/python/scope.hpp>
2124

2225
///////////////////////////////////////////////////////////////////////////////
2326
namespace boost { namespace python {
2427

28+
struct module;
29+
30+
namespace objects
31+
{
32+
struct class_base;
33+
}
34+
2535
namespace detail {
2636

37+
template <typename Func, class CallPolicies, class NameSpaceT>
38+
static void name_space_def(
39+
NameSpaceT& name_space,
40+
char const* name,
41+
Func f,
42+
CallPolicies const& policies,
43+
char const* doc,
44+
objects::class_base*
45+
)
46+
{
47+
name_space.def(
48+
name, f, policies, doc);
49+
}
50+
51+
template <typename Func, class CallPolicies>
52+
static void name_space_def(
53+
object& name_space,
54+
char const* name,
55+
Func f,
56+
CallPolicies const& policies,
57+
char const* doc,
58+
...
59+
)
60+
{
61+
scope within(name_space);
62+
63+
def(name, f, policies, doc);
64+
}
65+
66+
// For backward compatibility
67+
template <typename Func, class CallPolicies, class NameSpaceT>
68+
static void name_space_def(
69+
NameSpaceT& name_space,
70+
char const* name,
71+
Func f,
72+
CallPolicies const& policies,
73+
char const* doc,
74+
module*
75+
)
76+
{
77+
name_space.def(
78+
name, f, policies, doc);
79+
}
80+
2781
///////////////////////////////////////////////////////////////////////////////
2882
//
2983
// This Boost PP code generates expansions for
3084
//
31-
// template <typename StubsT, typename HolderT>
85+
// template <typename StubsT, typename NameSpaceT>
3286
// inline void
3387
// define_stub_function(
34-
// char const* name, StubsT s, HolderT& holder, boost::mpl::int_t<N>)
88+
// char const* name, StubsT s, NameSpaceT& name_space, boost::mpl::int_t<N>)
3589
// {
36-
// holder.def(name, &StubsT::func_N);
90+
// name_space.def(name, &StubsT::func_N);
3791
// }
3892
//
3993
// where N runs from 0 to BOOST_PYTHON_MAX_ARITY
@@ -42,7 +96,7 @@ namespace detail {
4296
//
4397
// 1. char const* name: function name that will be visible to python
4498
// 2. StubsT: a function stubs struct (see defaults_gen.hpp)
45-
// 3. HolderT& holder: a python::class_ or python::module instance
99+
// 3. NameSpaceT& name_space: a python::class_ or python::module instance
46100
// 4. int_t<N>: the Nth overloaded function (StubsT::func_N)
47101
// (see defaults_gen.hpp)
48102
// 5. char const* name: doc string
@@ -67,7 +121,7 @@ struct define_stub_function {};
67121
//
68122
// 1. char const* name: function name that will be visible to python
69123
// 2. StubsT: a function stubs struct (see defaults_gen.hpp)
70-
// 3. HolderT& holder: a python::class_ or python::module instance
124+
// 3. NameSpaceT& name_space: a python::class_ or python::module instance
71125
// 4. char const* name: doc string
72126
//
73127
// The def static member function calls a corresponding
@@ -79,27 +133,27 @@ struct define_stub_function {};
79133
template <int N>
80134
struct define_with_defaults_helper {
81135

82-
template <typename StubsT, typename HolderT>
136+
template <typename StubsT, typename NameSpaceT>
83137
static void
84-
def(char const* name, StubsT stubs, HolderT& holder, char const* doc)
138+
def(char const* name, StubsT stubs, NameSpaceT& name_space, char const* doc)
85139
{
86140
// define the NTH stub function of stubs
87-
define_stub_function<N>::define(name, stubs, holder, doc);
141+
define_stub_function<N>::define(name, stubs, name_space, doc);
88142
// call the next define_with_defaults_helper
89-
define_with_defaults_helper<N-1>::def(name, stubs, holder, doc);
143+
define_with_defaults_helper<N-1>::def(name, stubs, name_space, doc);
90144
}
91145
};
92146

93147
///////////////////////////////////////
94148
template <>
95149
struct define_with_defaults_helper<0> {
96150

97-
template <typename StubsT, typename HolderT>
151+
template <typename StubsT, typename NameSpaceT>
98152
static void
99-
def(char const* name, StubsT stubs, HolderT& holder, char const* doc)
153+
def(char const* name, StubsT stubs, NameSpaceT& name_space, char const* doc)
100154
{
101155
// define the Oth stub function of stubs
102-
define_stub_function<0>::define(name, stubs, holder, doc);
156+
define_stub_function<0>::define(name, stubs, name_space, doc);
103157
// return
104158
}
105159
};
@@ -110,12 +164,12 @@ struct define_stub_function {};
110164
//
111165
// 1. char const* name: function name that will be visible to python
112166
// 2. StubsT: a function stubs struct (see defaults_gen.hpp)
113-
// 3. HolderT& holder: a python::class_ or python::module instance
167+
// 3. NameSpaceT& name_space: a python::class_ or python::module instance
114168
// 4. SigT sig: Function signature typelist (see defaults_gen.hpp)
115169
// 5. char const* name: doc string
116170
//
117171
// This is the main entry point. This function recursively defines all
118-
// stub functions of StubT (see defaults_gen.hpp) in HolderT holder which
172+
// stub functions of StubT (see defaults_gen.hpp) in NameSpaceT name_space which
119173
// can be either a python::class_ or a python::module. The sig argument
120174
// is a typelist that specifies the return type, the class (for member
121175
// functions, and the arguments. Here are some SigT examples:
@@ -125,12 +179,12 @@ struct define_stub_function {};
125179
// void C::foo(int) mpl::type_list<void, C, int>
126180
//
127181
///////////////////////////////////////////////////////////////////////////////
128-
template <typename StubsT, typename HolderT, typename SigT>
182+
template <typename StubsT, typename NameSpaceT, typename SigT>
129183
inline void
130184
define_with_defaults(
131185
char const* name,
132186
StubsT,
133-
HolderT& holder,
187+
NameSpaceT& name_space,
134188
SigT sig,
135189
char const* doc)
136190
{
@@ -150,7 +204,7 @@ struct define_stub_function {};
150204

151205
typedef typename stubs_type::template gen<SigT> gen_type;
152206
define_with_defaults_helper<stubs_type::n_funcs-1>::def
153-
(name, gen_type(), holder, doc);
207+
(name, gen_type(), name_space, doc);
154208
}
155209

156210
} // namespace detail
@@ -163,24 +217,22 @@ struct define_stub_function {};
163217
#else // defined(BOOST_PP_IS_ITERATING)
164218
// PP vertical iteration code
165219

220+
166221
template <>
167222
struct define_stub_function<BOOST_PP_ITERATION()> {
168-
169-
template <typename StubsT, typename HolderT>
170-
static void
171-
define
172-
(
223+
template <typename StubsT, typename NameSpaceT>
224+
static void define(
173225
char const* name,
174226
StubsT,
175-
HolderT& holder,
227+
NameSpaceT& name_space,
176228
char const* doc
177229
)
178230
{
179-
holder.def(
231+
detail::name_space_def(name_space,
180232
name,
181233
&StubsT::BOOST_PP_CAT(func_, BOOST_PP_ITERATION()),
182234
default_call_policies(),
183-
doc);
235+
doc, &name_space);
184236
}
185237
};
186238

include/boost/python/scope.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ inline scope::scope(object const& new_scope)
3737

3838
inline scope::scope()
3939
: object(detail::borrowed_reference(
40-
current_scope
40+
current_scope ? current_scope : Py_None
4141
))
42-
, m_previous_scope(python::incref(current_scope))
42+
, m_previous_scope(python::xincref(current_scope))
4343
{
4444
}
4545

4646
inline scope::~scope()
4747
{
48-
python::decref(current_scope);
48+
python::xdecref(current_scope);
4949
current_scope = m_previous_scope;
5050
}
5151

src/module.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <boost/python/borrowed.hpp>
1414
#include <boost/python/object.hpp>
1515
#include <boost/python/detail/raw_pyobject.hpp>
16+
#include <boost/python/scope.hpp>
1617

1718
namespace boost { namespace python { namespace detail {
1819

@@ -37,6 +38,14 @@ void module_base::setattr_doc(const char* name, python::object const& x, char co
3738
objects::function::add_to_namespace(python::object(m_module), name, x, doc);
3839
}
3940

41+
void BOOST_PYTHON_DECL scope_setattr_doc(char const* name, object const& x, char const* doc)
42+
{
43+
// Use function::add_to_namespace to achieve overloading if
44+
// appropriate.
45+
scope current;
46+
objects::function::add_to_namespace(current, name, x, doc);
47+
}
48+
4049
void module_base::add(type_handle const& x)
4150
{
4251
this->setattr_doc(x->tp_name, python::object(x), 0);
@@ -74,6 +83,6 @@ BOOST_PYTHON_DECL void init_module(char const* name, void(*init_function)())
7483

7584
namespace boost { namespace python {
7685

77-
BOOST_PYTHON_DECL PyObject* scope::current_scope = Py_None;
86+
BOOST_PYTHON_DECL PyObject* scope::current_scope = 0;
7887

7988
}}

src/object/life_support.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ extern "C"
3737
}
3838

3939
PyTypeObject life_support_type = {
40-
PyObject_HEAD_INIT(&PyType_Type)
40+
PyObject_HEAD_INIT(0)//(&PyType_Type)
4141
0,
4242
"Boost.Python.life_support",
4343
sizeof(life_support),
@@ -84,8 +84,11 @@ PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient)
8484
if (nurse == Py_None)
8585
return incref(nurse);
8686

87-
if ((life_support_type.tp_flags & Py_TPFLAGS_READY) == 0)
87+
if (life_support_type.ob_type == 0)
88+
{
89+
life_support_type.ob_type = &PyType_Type;
8890
PyType_Ready(&life_support_type);
91+
}
8992

9093
life_support* system = PyObject_New(life_support, &life_support_type);
9194
if (!system)

test/back_reference.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
// "as is" without express or implied warranty, and with no claim as
55
// to its suitability for any purpose.
66
#include <boost/python/class.hpp>
7-
#include <boost/python/module.hpp>
7+
#include <boost/python/module_init.hpp>
8+
#include <boost/python/def.hpp>
89
#include <boost/python/has_back_reference.hpp>
910
#include <boost/python/back_reference.hpp>
1011
#include <boost/ref.hpp>
@@ -88,24 +89,23 @@ bool y_equality(back_reference<Y const&> y1, Y const& y2)
8889

8990
BOOST_PYTHON_MODULE_INIT(back_reference_ext)
9091
{
91-
module("back_reference_ext")
92-
.def("copy_Y", copy_Y, return_value_policy<copy_const_reference>())
93-
.def("copy_Z", copy_Z, return_value_policy<copy_const_reference>())
94-
.def("x_instances", &X::count)
95-
.add(
96-
class_<Y>("Y", args<int>())
97-
.def("value", &Y::value)
98-
.def("set", &Y::set)
99-
)
100-
101-
.add(
102-
class_<Z,std::auto_ptr<Z> >("Z", args<int>())
103-
.def("value", &Z::value)
104-
.def("set", &Z::set)
105-
)
106-
.def("y_identity", y_identity)
107-
.def("y_equality", y_equality)
92+
def("copy_Y", copy_Y, return_value_policy<copy_const_reference>());
93+
def("copy_Z", copy_Z, return_value_policy<copy_const_reference>());
94+
def("x_instances", &X::count);
95+
96+
class_<Y>("Y", args<int>())
97+
.def("value", &Y::value)
98+
.def("set", &Y::set)
10899
;
100+
101+
class_<Z,std::auto_ptr<Z> >("Z", args<int>())
102+
.def("value", &Z::value)
103+
.def("set", &Z::set)
104+
;
105+
106+
def("y_identity", y_identity);
107+
def("y_equality", y_equality);
108+
109109
}
110110

111111
#include "module_tail.cpp"

test/bienstman1.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#include <boost/python/module.hpp>
1+
#include <boost/python/module_init.hpp>
2+
#include <boost/python/def.hpp>
23
#include <boost/python/class.hpp>
34
#include <boost/python/reference_existing_object.hpp>
45
#include <boost/python/return_value_policy.hpp>

test/bienstman2.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#include <boost/python/module.hpp>
1+
#include <boost/python/module_init.hpp>
2+
#include <boost/python/def.hpp>
23
#include <boost/python/class.hpp>
34

45
struct C {};

test/bienstman3.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#include <boost/python/module.hpp>
1+
#include <boost/python/module_init.hpp>
2+
#include <boost/python/def.hpp>
23
#include <boost/python/class.hpp>
34

45
struct V

test/bienstman4.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
// "as is" without express or implied warranty, and with no claim as
55
// to its suitability for any purpose.
66

7-
#include <boost/python/module.hpp>
7+
#include <boost/python/module_init.hpp>
8+
#include <boost/python/def.hpp>
89
#include <boost/python/class.hpp>
910
#include <boost/python/implicit.hpp>
1011

test/bienstman5.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
// "as is" without express or implied warranty, and with no claim as
55
// to its suitability for any purpose.
66

7-
#include <boost/python/module.hpp>
7+
#include <boost/python/module_init.hpp>
8+
#include <boost/python/def.hpp>
89
#include <boost/python/class.hpp>
910
#include <boost/mpl/type_list.hpp>
1011

0 commit comments

Comments
 (0)