Skip to content

Commit 526d99f

Browse files
committed
Embed C++ objects directly in Python objects
[SVN r15192]
1 parent acbb5be commit 526d99f

22 files changed

+374
-211
lines changed

include/boost/python/class.hpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
# include <boost/mpl/bool_t.hpp>
2222
# include <boost/python/object/select_holder.hpp>
2323
# include <boost/python/object/class_wrapper.hpp>
24+
# include <boost/python/object/make_instance.hpp>
2425
# include <boost/python/data_members.hpp>
2526
# include <boost/utility.hpp>
2627
# include <boost/python/detail/operator_id.hpp>
@@ -56,7 +57,7 @@ namespace detail
5657
static inline void register_copy_constructor(mpl::bool_t<true> const&, SelectHolder const& , T* = 0)
5758
{
5859
typedef typename SelectHolder::type holder;
59-
force_instantiate(objects::class_wrapper<T,holder>());
60+
force_instantiate(objects::class_wrapper<T,holder, objects::make_instance<T,holder> >());
6061
SelectHolder::register_();
6162
}
6263

@@ -96,7 +97,7 @@ class class_ : public objects::class_base
9697
X3
9798
>::type>::type>::type held_type;
9899

99-
typedef objects::class_id class_id;
100+
typedef objects::select_holder<T,held_type> holder_selector;
100101

101102
typedef typename detail::select_bases<X1
102103
, typename detail::select_bases<X2
@@ -108,20 +109,19 @@ class class_ : public objects::class_base
108109
// passed to the base class constructor
109110
struct id_vector
110111
{
111-
typedef objects::class_id class_id;
112112
id_vector()
113113
{
114114
// Stick the derived class id into the first element of the array
115115
ids[0] = type_id<T>();
116116

117117
// Write the rest of the elements into succeeding positions.
118-
class_id* p = ids + 1;
118+
type_info* p = ids + 1;
119119
mpl::for_each<bases, void, detail::write_type_id>::execute(&p);
120120
}
121121

122122
BOOST_STATIC_CONSTANT(
123123
std::size_t, size = mpl::size<bases>::value + 1);
124-
class_id ids[size];
124+
type_info ids[size];
125125
};
126126
friend struct id_vector;
127127

@@ -146,6 +146,7 @@ class class_ : public objects::class_base
146146
{
147147
this->register_();
148148
this->def_init(InitArgs());
149+
this->set_instance_size(holder_selector::additional_size());
149150
}
150151

151152

@@ -155,6 +156,7 @@ class class_ : public objects::class_base
155156
{
156157
this->register_();
157158
this->def_init(InitArgs(), initdoc);
159+
this->set_instance_size(holder_selector::additional_size());
158160
}
159161

160162
// Wrap a member function or a non-member function which can take
@@ -237,7 +239,7 @@ class class_ : public objects::class_base
237239
return this->def("__init__",
238240
python::make_constructor<Args>(
239241
// Using runtime type selection works around a CWPro7 bug.
240-
objects::select_holder<T,held_type>((held_type*)0).get()
242+
holder_selector::execute((held_type*)0).get()
241243
)
242244
);
243245
}
@@ -252,7 +254,7 @@ class class_ : public objects::class_base
252254
python::make_constructor<Args>(
253255
helper::get_policy(policy_or_doc)
254256
// Using runtime type selection works around a CWPro7 bug.
255-
, objects::select_holder<T,held_type>((held_type*)0).get()
257+
, holder_selector::execute((held_type*)0).get()
256258
)
257259
, helper::get_doc(policy_or_doc, doc)
258260
);
@@ -389,7 +391,7 @@ inline void class_<T,X1,X2,X3>::register_() const
389391

390392
detail::register_copy_constructor<T>(
391393
mpl::bool_t<is_copyable>()
392-
, objects::select_holder<T,held_type>((held_type*)0)
394+
, holder_selector::execute((held_type*)0)
393395
);
394396
}
395397

@@ -402,6 +404,7 @@ inline class_<T,X1,X2,X3>::class_()
402404
this->register_();
403405
detail::force_instantiate(sizeof(detail::assert_default_constructible(T())));
404406
this->def_init();
407+
this->set_instance_size(holder_selector::additional_size());
405408
}
406409

407410
template <class T, class X1, class X2, class X3>
@@ -419,6 +422,7 @@ inline class_<T,X1,X2,X3>::class_(char const* name, char const* doc)
419422
this->register_();
420423
detail::force_instantiate(sizeof(detail::assert_default_constructible(T())));
421424
this->def_init();
425+
this->set_instance_size(holder_selector::additional_size());
422426
}
423427

424428
template <class T, class X1, class X2, class X3>

include/boost/python/converter/smart_ptr.hpp

Lines changed: 0 additions & 70 deletions
This file was deleted.

include/boost/python/instance_holder.hpp

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

99
# include <boost/python/detail/config.hpp>
1010
# include <boost/utility.hpp>
11+
# include <boost/python/type_id.hpp>
12+
# include <cstddef>
1113

1214
namespace boost { namespace python {
1315

@@ -25,6 +27,16 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable
2527

2628
void install(PyObject* inst) throw();
2729

30+
// These functions should probably be located elsewhere.
31+
32+
// Allocate storage for an object of the given size at the given
33+
// offset in the Python instance<> object if bytes are available
34+
// there. Otherwise allocate size bytes of heap memory.
35+
static void* allocate(PyObject*, std::size_t offset, std::size_t size);
36+
37+
// Deallocate storage from the heap if it was not carved out of
38+
// the given Python object by allocate(), above.
39+
static void deallocate(PyObject*, void* storage) throw();
2840
private:
2941
instance_holder* m_next;
3042
};

include/boost/python/object.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# include <boost/python/object_items.hpp>
1212
# include <boost/python/object_slices.hpp>
1313
# include <boost/python/object_operators.hpp>
14+
# include <boost/python/converter/arg_to_python.hpp>
1415

1516
namespace boost { namespace python {
1617

include/boost/python/object/class.hpp

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,14 @@
99
# include <boost/python/detail/wrap_python.hpp>
1010
# include <boost/python/detail/config.hpp>
1111
# include <boost/utility.hpp>
12-
# include <boost/python/type_id.hpp>
13-
# include <boost/python/handle.hpp>
1412
# include <boost/python/instance_holder.hpp>
1513
# include <boost/python/object_core.hpp>
1614
# include <cstddef>
1715

1816
namespace boost { namespace python {
1917

20-
class module;
21-
2218
namespace objects {
2319

24-
// To identify a class, we don't need cv/reference decorations
25-
typedef type_info class_id;
26-
2720
struct BOOST_PYTHON_DECL class_base : python::api::object
2821
{
2922
// constructor
@@ -33,6 +26,7 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
3326
, std::size_t num_types // A list of class_ids. The first is the type
3427
, class_id const*const types // this is wrapping. The rest are the types of
3528
// any bases.
29+
3630
, char const* doc = 0 // Docstring, if any.
3731
);
3832

@@ -41,21 +35,17 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
4135
void add_property(char const* name, object const& fget, object const& fset);
4236
void setattr(char const* name, object const&);
4337
void enable_pickling(bool getstate_manages_dict);
44-
void def_no_init();
45-
};
4638

47-
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id);
39+
// Set a special attribute in the class which tells Boost.Python
40+
// to allocate extra bytes for embedded C++ objects in Python
41+
// instances.
42+
void set_instance_size(std::size_t bytes);
4843

49-
// Each extension instance will be one of these
50-
struct instance
51-
{
52-
PyObject_HEAD
53-
instance_holder* objects;
44+
// Set an __init__ function which throws an appropriate exception
45+
// for abstract classes.
46+
void def_no_init();
5447
};
5548

56-
BOOST_PYTHON_DECL type_handle class_metatype();
57-
BOOST_PYTHON_DECL type_handle class_type();
58-
5949
}}} // namespace boost::python::objects
6050

6151
#endif // CLASS_DWA20011214_HPP
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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 CLASS_DETAIL_DWA200295_HPP
7+
# define CLASS_DETAIL_DWA200295_HPP
8+
9+
# include <boost/python/handle.hpp>
10+
# include <boost/python/type_id.hpp>
11+
12+
namespace boost { namespace python { namespace objects {
13+
14+
BOOST_PYTHON_DECL type_handle registered_class_object(type_info id);
15+
BOOST_PYTHON_DECL type_handle class_metatype();
16+
BOOST_PYTHON_DECL type_handle class_type();
17+
18+
}}} // namespace boost::python::object
19+
20+
#endif // CLASS_DETAIL_DWA200295_HPP

include/boost/python/object/class_wrapper.hpp

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,21 @@
66
#ifndef CLASS_WRAPPER_DWA20011221_HPP
77
# define CLASS_WRAPPER_DWA20011221_HPP
88

9-
# include <boost/python/handle.hpp>
109
# include <boost/python/to_python_converter.hpp>
11-
# include <boost/python/converter/registered.hpp>
1210
# include <boost/ref.hpp>
1311

1412
namespace boost { namespace python { namespace objects {
1513

16-
template <class Src, class Holder>
17-
struct copy_construct_instance
18-
{
19-
static Holder* execute(PyObject* instance, Src const& x)
20-
{
21-
return new Holder(instance, cref(x));
22-
}
23-
};
24-
2514
// Used to convert objects of type Src to wrapped C++ classes by
2615
// building a new instance object and installing a Holder constructed
2716
// from the Src object.
28-
template <class Src, class Holder, class MakeHolder = copy_construct_instance<Src,Holder> >
17+
template <class Src, class Holder, class MakeInstance>
2918
struct class_wrapper
30-
: to_python_converter<Src,class_wrapper<Src,Holder,MakeHolder> >
19+
: to_python_converter<Src,class_wrapper<Src,Holder,MakeInstance> >
3120
{
3221
static PyObject* convert(Src const& x)
3322
{
34-
// Get the class object associated with the wrapped type
35-
typedef typename Holder::value_type value_type;
36-
PyTypeObject* class_object = converter::registered<value_type>::converters.class_object;
37-
38-
// Don't call the type directly to do the construction, since
39-
// that would require the registration of an appropriate
40-
// __init__ function.
41-
PyObject* raw_result = class_object->tp_alloc(class_object, 0);
42-
43-
if (raw_result == 0)
44-
return 0;
45-
46-
// Everything's OK; Bypass NULL checks but guard against
47-
// exceptions.
48-
handle<> result(python::allow_null(raw_result));
49-
50-
// Build a value_holder to contain the object using the copy
51-
// constructor
52-
Holder* p = MakeHolder::execute(raw_result, x);
53-
54-
// Install it in the instance
55-
p->install(raw_result);
56-
57-
// Return the new result
58-
return result.release();
23+
return MakeInstance::execute(cref(x));
5924
}
6025
};
6126

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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 INSTANCE_DWA200295_HPP
7+
# define INSTANCE_DWA200295_HPP
8+
9+
# include <boost/python/detail/wrap_python.hpp>
10+
# include <boost/type_traits/alignment_traits.hpp>
11+
# include <cstddef>
12+
13+
namespace boost { namespace python { namespace objects {
14+
15+
// Each extension instance will be one of these
16+
template <class Data = char>
17+
struct instance
18+
{
19+
PyObject_VAR_HEAD
20+
PyObject* dict;
21+
PyObject* weakrefs;
22+
instance_holder* objects;
23+
24+
BOOST_STATIC_CONSTANT(std::size_t, alignment = alignment_of<Data>::value);
25+
typedef typename type_with_alignment<alignment>::type align_t;
26+
27+
union
28+
{
29+
align_t align;
30+
char bytes[sizeof(Data)];
31+
} storage;
32+
};
33+
34+
template <class Data>
35+
struct additional_instance_size
36+
{
37+
typedef instance<Data> instance_data;
38+
typedef instance<char> instance_char;
39+
BOOST_STATIC_CONSTANT(
40+
std::size_t, value = sizeof(instance_data) - offsetof(instance_char,storage));
41+
};
42+
43+
}}} // namespace boost::python::object
44+
45+
#endif // INSTANCE_DWA200295_HPP

0 commit comments

Comments
 (0)