2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 18:12:43 +00:00

Embed C++ objects directly in Python objects

[SVN r15192]
This commit is contained in:
Dave Abrahams
2002-09-07 04:44:17 +00:00
parent acbb5be6ab
commit 526d99f832
22 changed files with 375 additions and 212 deletions

View File

@@ -21,6 +21,7 @@
# include <boost/mpl/bool_t.hpp>
# include <boost/python/object/select_holder.hpp>
# include <boost/python/object/class_wrapper.hpp>
# include <boost/python/object/make_instance.hpp>
# include <boost/python/data_members.hpp>
# include <boost/utility.hpp>
# include <boost/python/detail/operator_id.hpp>
@@ -56,7 +57,7 @@ namespace detail
static inline void register_copy_constructor(mpl::bool_t<true> const&, SelectHolder const& , T* = 0)
{
typedef typename SelectHolder::type holder;
force_instantiate(objects::class_wrapper<T,holder>());
force_instantiate(objects::class_wrapper<T,holder, objects::make_instance<T,holder> >());
SelectHolder::register_();
}
@@ -96,7 +97,7 @@ class class_ : public objects::class_base
X3
>::type>::type>::type held_type;
typedef objects::class_id class_id;
typedef objects::select_holder<T,held_type> holder_selector;
typedef typename detail::select_bases<X1
, typename detail::select_bases<X2
@@ -108,20 +109,19 @@ class class_ : public objects::class_base
// passed to the base class constructor
struct id_vector
{
typedef objects::class_id class_id;
id_vector()
{
// Stick the derived class id into the first element of the array
ids[0] = type_id<T>();
// Write the rest of the elements into succeeding positions.
class_id* p = ids + 1;
type_info* p = ids + 1;
mpl::for_each<bases, void, detail::write_type_id>::execute(&p);
}
BOOST_STATIC_CONSTANT(
std::size_t, size = mpl::size<bases>::value + 1);
class_id ids[size];
type_info ids[size];
};
friend struct id_vector;
@@ -146,6 +146,7 @@ class class_ : public objects::class_base
{
this->register_();
this->def_init(InitArgs());
this->set_instance_size(holder_selector::additional_size());
}
@@ -155,6 +156,7 @@ class class_ : public objects::class_base
{
this->register_();
this->def_init(InitArgs(), initdoc);
this->set_instance_size(holder_selector::additional_size());
}
// Wrap a member function or a non-member function which can take
@@ -237,7 +239,7 @@ class class_ : public objects::class_base
return this->def("__init__",
python::make_constructor<Args>(
// Using runtime type selection works around a CWPro7 bug.
objects::select_holder<T,held_type>((held_type*)0).get()
holder_selector::execute((held_type*)0).get()
)
);
}
@@ -252,7 +254,7 @@ class class_ : public objects::class_base
python::make_constructor<Args>(
helper::get_policy(policy_or_doc)
// Using runtime type selection works around a CWPro7 bug.
, objects::select_holder<T,held_type>((held_type*)0).get()
, holder_selector::execute((held_type*)0).get()
)
, helper::get_doc(policy_or_doc, doc)
);
@@ -389,7 +391,7 @@ inline void class_<T,X1,X2,X3>::register_() const
detail::register_copy_constructor<T>(
mpl::bool_t<is_copyable>()
, objects::select_holder<T,held_type>((held_type*)0)
, holder_selector::execute((held_type*)0)
);
}
@@ -402,6 +404,7 @@ inline class_<T,X1,X2,X3>::class_()
this->register_();
detail::force_instantiate(sizeof(detail::assert_default_constructible(T())));
this->def_init();
this->set_instance_size(holder_selector::additional_size());
}
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)
this->register_();
detail::force_instantiate(sizeof(detail::assert_default_constructible(T())));
this->def_init();
this->set_instance_size(holder_selector::additional_size());
}
template <class T, class X1, class X2, class X3>

View File

@@ -1,70 +0,0 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef SMART_PTR_DWA2002123_HPP
# define SMART_PTR_DWA2002123_HPP
# include <boost/python/converter/class.hpp>
# include <boost/python/object/pointer_holder.hpp>
namespace boost { namespace python { namespace converter {
template <class Pointer, class Value>
class smart_ptr_wrapper
: wrapper<Pointer const&>
{
smart_ptr_wrapper(ref const& type_)
: m_class_object(type_)
{
assert(type_->ob_type == (PyTypeObject*)class_metatype().get());
}
PyObject* convert(Pointer x) const;
private:
ref m_class_object;
smart_ptr_converters();
}
//
// implementations
//
template <class Pointer, class Value>
PyObject* smart_ptr_wrapper<Pointer,Value>::convert(Pointer x) const
{
if (x.operator->() == 0)
return detail::none();
// Don't call the type to do the construction, since that
// would require the registration of an __init__ copy
// constructor. Instead, just construct the object in place.
PyObject* raw_result = (PyObject*)PyObject_New(
instance, (PyTypeObject*)m_class_object.get());
if (raw_result == 0)
return 0;
// Everything's OK; Bypass NULL checks but guard against
// exceptions.
ref result(raw_result, ref::allow_null());
// Build a value_holder to contain the object using the copy
// constructor
objects::pointer_holder<Pointer,Value>*
p = new objects::pointer_holder<Pointer,Value>(x);
// Install it in the instance
p->install(raw_result);
// Return the new result
return result.release();
}
}}} // namespace boost::python::converter
#endif // SMART_PTR_DWA2002123_HPP

View File

@@ -8,6 +8,8 @@
# include <boost/python/detail/config.hpp>
# include <boost/utility.hpp>
# include <boost/python/type_id.hpp>
# include <cstddef>
namespace boost { namespace python {
@@ -25,6 +27,16 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable
void install(PyObject* inst) throw();
// These functions should probably be located elsewhere.
// Allocate storage for an object of the given size at the given
// offset in the Python instance<> object if bytes are available
// there. Otherwise allocate size bytes of heap memory.
static void* allocate(PyObject*, std::size_t offset, std::size_t size);
// Deallocate storage from the heap if it was not carved out of
// the given Python object by allocate(), above.
static void deallocate(PyObject*, void* storage) throw();
private:
instance_holder* m_next;
};

View File

@@ -11,6 +11,7 @@
# include <boost/python/object_items.hpp>
# include <boost/python/object_slices.hpp>
# include <boost/python/object_operators.hpp>
# include <boost/python/converter/arg_to_python.hpp>
namespace boost { namespace python {

View File

@@ -9,21 +9,14 @@
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/detail/config.hpp>
# include <boost/utility.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/handle.hpp>
# include <boost/python/instance_holder.hpp>
# include <boost/python/object_core.hpp>
# include <cstddef>
namespace boost { namespace python {
class module;
namespace objects {
// To identify a class, we don't need cv/reference decorations
typedef type_info class_id;
struct BOOST_PYTHON_DECL class_base : python::api::object
{
// constructor
@@ -33,6 +26,7 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
, std::size_t num_types // A list of class_ids. The first is the type
, class_id const*const types // this is wrapping. The rest are the types of
// any bases.
, char const* doc = 0 // Docstring, if any.
);
@@ -41,21 +35,17 @@ struct BOOST_PYTHON_DECL class_base : python::api::object
void add_property(char const* name, object const& fget, object const& fset);
void setattr(char const* name, object const&);
void enable_pickling(bool getstate_manages_dict);
// Set a special attribute in the class which tells Boost.Python
// to allocate extra bytes for embedded C++ objects in Python
// instances.
void set_instance_size(std::size_t bytes);
// Set an __init__ function which throws an appropriate exception
// for abstract classes.
void def_no_init();
};
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id);
// Each extension instance will be one of these
struct instance
{
PyObject_HEAD
instance_holder* objects;
};
BOOST_PYTHON_DECL type_handle class_metatype();
BOOST_PYTHON_DECL type_handle class_type();
}}} // namespace boost::python::objects
#endif // CLASS_DWA20011214_HPP

View File

@@ -0,0 +1,20 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CLASS_DETAIL_DWA200295_HPP
# define CLASS_DETAIL_DWA200295_HPP
# include <boost/python/handle.hpp>
# include <boost/python/type_id.hpp>
namespace boost { namespace python { namespace objects {
BOOST_PYTHON_DECL type_handle registered_class_object(type_info id);
BOOST_PYTHON_DECL type_handle class_metatype();
BOOST_PYTHON_DECL type_handle class_type();
}}} // namespace boost::python::object
#endif // CLASS_DETAIL_DWA200295_HPP

View File

@@ -6,56 +6,21 @@
#ifndef CLASS_WRAPPER_DWA20011221_HPP
# define CLASS_WRAPPER_DWA20011221_HPP
# include <boost/python/handle.hpp>
# include <boost/python/to_python_converter.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/ref.hpp>
namespace boost { namespace python { namespace objects {
template <class Src, class Holder>
struct copy_construct_instance
{
static Holder* execute(PyObject* instance, Src const& x)
{
return new Holder(instance, cref(x));
}
};
// Used to convert objects of type Src to wrapped C++ classes by
// building a new instance object and installing a Holder constructed
// from the Src object.
template <class Src, class Holder, class MakeHolder = copy_construct_instance<Src,Holder> >
template <class Src, class Holder, class MakeInstance>
struct class_wrapper
: to_python_converter<Src,class_wrapper<Src,Holder,MakeHolder> >
: to_python_converter<Src,class_wrapper<Src,Holder,MakeInstance> >
{
static PyObject* convert(Src const& x)
{
// Get the class object associated with the wrapped type
typedef typename Holder::value_type value_type;
PyTypeObject* class_object = converter::registered<value_type>::converters.class_object;
// Don't call the type directly to do the construction, since
// that would require the registration of an appropriate
// __init__ function.
PyObject* raw_result = class_object->tp_alloc(class_object, 0);
if (raw_result == 0)
return 0;
// Everything's OK; Bypass NULL checks but guard against
// exceptions.
handle<> result(python::allow_null(raw_result));
// Build a value_holder to contain the object using the copy
// constructor
Holder* p = MakeHolder::execute(raw_result, x);
// Install it in the instance
p->install(raw_result);
// Return the new result
return result.release();
return MakeInstance::execute(cref(x));
}
};

View File

@@ -0,0 +1,45 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef INSTANCE_DWA200295_HPP
# define INSTANCE_DWA200295_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/type_traits/alignment_traits.hpp>
# include <cstddef>
namespace boost { namespace python { namespace objects {
// Each extension instance will be one of these
template <class Data = char>
struct instance
{
PyObject_VAR_HEAD
PyObject* dict;
PyObject* weakrefs;
instance_holder* objects;
BOOST_STATIC_CONSTANT(std::size_t, alignment = alignment_of<Data>::value);
typedef typename type_with_alignment<alignment>::type align_t;
union
{
align_t align;
char bytes[sizeof(Data)];
} storage;
};
template <class Data>
struct additional_instance_size
{
typedef instance<Data> instance_data;
typedef instance<char> instance_char;
BOOST_STATIC_CONSTANT(
std::size_t, value = sizeof(instance_data) - offsetof(instance_char,storage));
};
}}} // namespace boost::python::object
#endif // INSTANCE_DWA200295_HPP

View File

@@ -8,6 +8,7 @@
# include <boost/python/object/iterator_core.hpp>
# include <boost/python/class_fwd.hpp>
# include <boost/python/object/class_detail.hpp>
# include <boost/python/return_value_policy.hpp>
# include <boost/python/copy_const_reference.hpp>
# include <boost/python/object/function_object.hpp>

View File

@@ -10,7 +10,6 @@
# define MAKE_HOLDER_DWA20011215_HPP
# include <boost/python/object/forward.hpp>
# include <boost/python/object/class.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/detail/preprocessor.hpp>
@@ -20,6 +19,8 @@
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/repeat.hpp>
# include <cstddef>
namespace boost { namespace python { namespace objects {
template <int nargs> struct make_holder;
@@ -57,8 +58,17 @@ struct make_holder<N>
PyObject* p
BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, t, a))
{
(new Holder(
p BOOST_PP_REPEAT(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p);
typedef instance<Holder> instance_t;
void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder));
try {
(new (memory) Holder(
p BOOST_PP_REPEAT(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p);
}
catch(...) {
Holder::deallocate(p, memory);
throw;
}
}
};
};

View File

@@ -0,0 +1,72 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef MAKE_INSTANCE_DWA200296_HPP
# define MAKE_INSTANCE_DWA200296_HPP
# include <boost/python/object/instance.hpp>
# include <boost/python/converter/registered.hpp>
namespace boost { namespace python { namespace objects {
template <class T, class Holder>
struct make_instance
{
typedef objects::instance<Holder> instance_t;
template <class Arg>
static PyObject* execute(Arg& x)
{
BOOST_STATIC_ASSERT(is_class<T>::value);
PyTypeObject* type = converter::registered<T>::converters.class_object;
PyObject* raw_result = type->tp_alloc(
type, objects::additional_instance_size<Holder>::value);
if (raw_result != 0)
{
instance_t* result = (instance_t*)raw_result;
try
{
// construct the new C++ object and install the pointer
// in the Python object.
construct(result, x)->install(raw_result);
}
catch(...)
{
Py_DECREF(raw_result); // reclaim the Python object
throw;
}
// Note the position of the internally-stored Holder,
// for the sake of destruction
result->ob_size = offsetof(instance_t, storage);
}
return raw_result;
}
private:
// Kind of a hack to support code re-use. The first form is used
// to construct holders around pointers or smart pointers. The
// second form is used to construct holders around by-value
// returns. We have to pass a pointer to the owning Python object
// to the second form in order to make it forward the 2nd argument
// on to the constructor of its embedded T object.
template <class Arg>
static Holder* construct(instance_t* result, Arg& x)
{
return new ((void*)&result->storage) Holder(x);
}
static Holder* construct(instance_t* result, reference_wrapper<T const> x)
{
return new ((void*)&result->storage) Holder((PyObject*)result, x);
}
};
}}} // namespace boost::python::object
#endif // MAKE_INSTANCE_DWA200296_HPP

View File

@@ -6,7 +6,6 @@
#ifndef BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP
#define BOOST_PYTHON_OBJECT_PICKLE_SUPPORT_RWGK20020603_HPP
#include <boost/python/object/class.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/object_core.hpp>

View File

@@ -12,10 +12,14 @@
# include <boost/python/object/value_holder.hpp>
# include <boost/python/object/pointer_holder.hpp>
# include <boost/python/object/find_instance.hpp>
# include <boost/python/object/make_instance.hpp>
# include <boost/python/object/instance.hpp>
# include <boost/type.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/same_traits.hpp>
# include <boost/type_traits/alignment_traits.hpp>
# include <boost/mpl/bool_t.hpp>
# include <cstddef>
namespace boost { namespace python { namespace objects {
@@ -96,7 +100,7 @@ namespace detail
objects::class_wrapper<
Ptr
, type
, construct_from_pointer>());
, make_instance<T,type> >());
python::detail::force_instantiate(
instance_finder<Ptr>::registration);
@@ -104,24 +108,40 @@ namespace detail
};
}
template <class T, class NotSpecified>
inline detail::select_value_holder<T,T> select_holder(python::detail::not_specified*, T* = 0, NotSpecified* = 0)
{
return detail::select_value_holder<T,T>();
}
template <class T, class Held>
inline detail::select_value_holder<T, Held> select_holder(T*, Held* = 0)
struct select_holder
{
return detail::select_value_holder<T, Held>();
}
static inline std::size_t additional_size()
{
return additional_size_helper(execute((Held*)0));
}
static inline detail::select_value_holder<T,T>
execute(python::detail::not_specified*)
{
return detail::select_value_holder<T,T>();
}
static inline detail::select_value_holder<T, Held>
execute(T*)
{
return detail::select_value_holder<T, Held>();
}
template <class T, class Ptr>
detail::select_pointer_holder<T,Ptr> select_holder(void*, Ptr* = 0, T* = 0)
{
return detail::select_pointer_holder<T,Ptr>();
}
static inline detail::select_pointer_holder<T,Held>
execute(void*)
{
return detail::select_pointer_holder<T,Held>();
}
private:
template <class Selector>
static inline std::size_t additional_size_helper(Selector const&)
{
typedef typename Selector::type holder;
return additional_instance_size<holder>::value;
}
};
}}} // namespace boost::python::objects

View File

@@ -10,7 +10,7 @@
# define VALUE_HOLDER_DWA20011215_HPP
# include <boost/python/object/value_holder_fwd.hpp>
# include <boost/python/object/class.hpp>
# include <boost/python/instance_holder.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/object/inheritance.hpp>
# include <boost/python/object/find_instance.hpp>

View File

@@ -9,7 +9,6 @@
# include <boost/type.hpp>
# include <boost/python/handle.hpp>
# include <boost/python/converter/arg_to_python.hpp>
# include <boost/python/call.hpp>
# include <boost/python/slice_nil.hpp>
# include <boost/python/detail/raw_pyobject.hpp>
@@ -22,6 +21,11 @@
namespace boost { namespace python {
namespace converter
{
template <class T> struct arg_to_python;
}
// Put this in an inner namespace so that the generalized operators won't take over
namespace api
{

View File

@@ -8,10 +8,12 @@
# include <boost/type_traits/object_traits.hpp>
# include <boost/python/object/pointer_holder.hpp>
# include <boost/python/object/instance.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/detail/unwind_type.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/shared_ptr.hpp>
# include <boost/python/object/make_instance.hpp>
# include <memory>
namespace boost { namespace python {
@@ -32,7 +34,7 @@ namespace detail
{
struct make_owning_holder
{
typedef instance_holder* result_type;
typedef PyObject* result_type;
template <class T>
static result_type execute(T* p)
{
@@ -41,20 +43,22 @@ namespace detail
typedef boost::shared_ptr<T> smart_pointer;
# else
typedef std::auto_ptr<T> smart_pointer;
# endif
return new objects::pointer_holder<smart_pointer, T>(
smart_pointer(p));
# endif
typedef objects::pointer_holder<smart_pointer, T> holder_t;
smart_pointer ptr(p);
return objects::make_instance<T, holder_t>::execute(ptr);
}
};
struct make_reference_holder
{
typedef instance_holder* result_type;
typedef PyObject* result_type;
template <class T>
static result_type execute(T* p)
{
return new objects::pointer_holder<T*, T>(p);
typedef objects::pointer_holder<T*, T> holder_t;
return objects::make_instance<T, holder_t>::execute(p);
}
};
@@ -99,26 +103,8 @@ inline PyObject* to_python_indirect<T,MakeHolder>::operator()(T x) const
PyObject* const null_result = detail::null_pointer_to_none(x, 1L);
if (null_result != 0)
return null_result;
PyObject* raw_result = type()->tp_alloc(type(), 0);
if (raw_result == 0)
return 0;
// Everything's OK; Bypass NULL checks but guard against
// exceptions.
handle<> result(python::allow_null(raw_result));
// Build a value_holder to contain the object using the copy
// constructor
instance_holder* p =
detail::unwind_type<MakeHolder>(x);
// Install it in the instance
p->install(raw_result);
// Return the new result
return result.release();
return detail::unwind_type<MakeHolder>(x);
}
template <class T, class MakeHolder>

View File

@@ -3,9 +3,11 @@
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/object/class.hpp>
#include <boost/python/object/instance.hpp>
#include <boost/python/object/class_detail.hpp>
#include <boost/python/scope.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/object/find_instance.hpp>
#include <boost/python/object/pickle_support.hpp>
#include <boost/python/detail/map_entry.hpp>
@@ -17,6 +19,9 @@
#include <boost/bind.hpp>
#include <functional>
#include <vector>
#include <cstddef>
#include <new>
#include <structmember.h>
namespace boost { namespace python {
@@ -98,8 +103,8 @@ static PyTypeObject class_metatype_object = {
void instance_holder::install(PyObject* self) throw()
{
assert(self->ob_type->ob_type == &class_metatype_object);
m_next = ((objects::instance*)self)->objects;
((objects::instance*)self)->objects = this;
m_next = ((objects::instance<>*)self)->objects;
((objects::instance<>*)self)->objects = this;
}
@@ -121,25 +126,89 @@ namespace objects
{
static void instance_dealloc(PyObject* inst)
{
instance* kill_me = (instance*)inst;
instance<>* kill_me = (instance<>*)inst;
for (instance_holder* p = kill_me->objects, *next; p != 0; p = next)
{
next = p->next();
delete p;
p->~instance_holder();
instance_holder::deallocate(inst, dynamic_cast<void*>(p));
}
// Python 2.2.1 won't add weak references automatically when
// tp_itemsize > 0, so we need to manage that
// ourselves. Accordingly, we also have to clean up the
// weakrefs ourselves.
if (kill_me->weakrefs != NULL)
PyObject_ClearWeakRefs(inst);
Py_XDECREF(kill_me->dict);
inst->ob_type->tp_free(inst);
}
static PyObject *
instance_new(PyTypeObject* type_, PyObject* args, PyObject *kw)
{
// Attempt to find the __instance_size__ attribute. If not present, no problem.
PyObject* d = type_->tp_dict;
PyObject* instance_size_obj = PyObject_GetAttrString(d, "__instance_size__");
long instance_size = 0;
if (instance_size != 0)
instance_size = PyInt_AsLong(instance_size_obj);
if (instance_size < 0)
instance_size = 0;
PyErr_Clear(); // Clear any errors that may have occurred.
instance<>* result = (instance<>*)type_->tp_alloc(type_, instance_size);
if (result)
{
// Guido says we can use ob_size for any purpose we
// like, so we'll store the total size of the object
// there. A negative number indicates that the extra
// instance memory is not yet allocated to any holders.
result->ob_size = -(offsetof(instance<>,storage) + instance_size);
}
return (PyObject*)result;
}
static PyObject* instance_get_dict(PyObject* op, void*)
{
instance<>* inst = downcast<instance<> >(op);
if (inst->dict == 0)
inst->dict = PyDict_New();
return python::xincref(inst->dict);
}
static int instance_set_dict(PyObject* op, PyObject* dict, void*)
{
instance<>* inst = downcast<instance<> >(op);
python::xdecref(inst->dict);
inst->dict = python::incref(dict);
return 0;
}
}
static PyGetSetDef instance_getsets[] = {
{"__dict__", instance_get_dict, instance_set_dict, NULL},
{0}
};
static PyMemberDef instance_members[] = {
{"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0},
{0}
};
static PyTypeObject class_type_object = {
PyObject_HEAD_INIT(0) //&class_metatype_object)
0,
"Boost.Python.instance",
sizeof(instance),
0,
offsetof(instance<>,storage), /* tp_basicsize */
1, /* tp_itemsize */
instance_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
@@ -161,20 +230,20 @@ namespace objects
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
offsetof(instance<>,weakrefs), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, //&PyBaseObject_Type, /* tp_base */
instance_members, /* tp_members */
instance_getsets, /* tp_getset */
0, //&PyBaseObject_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
offsetof(instance<>,dict), /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew
instance_new /* tp_new */
};
BOOST_PYTHON_DECL type_handle class_type()
@@ -195,7 +264,7 @@ namespace objects
if (inst->ob_type->ob_type != &class_metatype_object)
return 0;
instance* self = reinterpret_cast<instance*>(inst);
instance<>* self = reinterpret_cast<instance<>*>(inst);
for (instance_holder* match = self->objects; match != 0; match = match->next())
{
@@ -302,6 +371,11 @@ namespace objects
this->attr("__doc__") = doc;
}
void class_base::set_instance_size(std::size_t instance_size)
{
this->attr("__instance_size__") = instance_size;
}
extern "C"
{
// This declaration needed due to broken Python 2.2 headers
@@ -369,4 +443,40 @@ namespace objects
}
} // namespace objects
void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
{
assert(self_->ob_type->ob_type == &class_metatype_object);
objects::instance<>* self = (objects::instance<>*)self_;
int total_size_needed = holder_offset + holder_size;
if (-self->ob_size >= total_size_needed)
{
// holder_offset should at least point into the variable-sized part
assert(holder_offset >= offsetof(objects::instance<>,storage));
// Record the fact that the storage is occupied, noting where it starts
self->ob_size = holder_offset;
return (char*)self + holder_offset;
}
else
{
void* const result = PyMem_Malloc(holder_size);
if (result == 0)
throw std::bad_alloc();
return result;
}
}
void instance_holder::deallocate(PyObject* self_, void* storage) throw()
{
assert(self_->ob_type->ob_type == &class_metatype_object);
objects::instance<>* self = (objects::instance<>*)self_;
if (storage != (char*)self + self->ob_size)
{
PyMem_Free(storage);
}
}
}} // namespace boost::python

View File

@@ -301,11 +301,11 @@ extern "C"
}
}
static PyGetSetDef function_getsetlist[] = {
{"__name__", (getter)function_get_name, 0 },
{"__doc__", (getter)function_get_doc, (setter)function_set_doc},
{NULL} /* Sentinel */
};
static PyGetSetDef function_getsetlist[] = {
{"__name__", (getter)function_get_name, 0 },
{"__doc__", (getter)function_get_doc, (setter)function_set_doc},
{NULL} /* Sentinel */
};
PyTypeObject function_type = {
PyObject_HEAD_INIT(0)

View File

@@ -52,7 +52,7 @@ public:
BOOST_PYTHON_MODULE_INIT(cltree)
{
boost::python::class_<basic>("basic")
.def("__repr__",&basic::repr)
.def("__repr__",&basic::repr)
;
boost::python::class_<constant, boost::python::bases<basic>, boost::noncopyable>("constant")
@@ -60,7 +60,7 @@ BOOST_PYTHON_MODULE_INIT(cltree)
boost::python::class_<symbol, symbol_wrapper, boost::noncopyable>("symbol")
;
;
boost::python::class_<variable, boost::python::bases<basic>, variable_wrapper>("variable")
;

View File

@@ -17,7 +17,6 @@
#endif
using namespace boost::python;
using namespace std;
char const* const format = "int(%s); char(%s); string(%s); double(%s); ";
@@ -169,7 +168,7 @@ BOOST_PYTHON_MODULE_INIT(defaults_ext)
.def_init(args<int, char, std::string>())
.def_init(args<int, char, std::string, double>())
# endif
.def("get_state", &X::get_state)
.def("get_state", &X::get_state)
.def("bar", &X::bar, X_bar_stubs())
.def("bar2", &X::bar2, X_bar_stubs2(), return_internal_reference<>())
.def("foo", (object(X::*)(std::string, bool) const)0, X_foo_2_stubs())

View File

@@ -216,12 +216,6 @@ BOOST_PYTHON_MODULE_INIT(m1)
lvalue_from_pytype<extract_identity<SimpleObject>,&SimpleType>();
// Insert the metaclass for all extension classes
scope().attr("xclass") = boost::python::objects::class_metatype();
// Insert the base class for all extension classes
scope().attr("xinst") = boost::python::objects::class_type();
def("new_noddy", new_noddy);
def("new_simple", new_simple);

View File

@@ -8,6 +8,7 @@
#include <boost/python/object/select_holder.hpp>
#include <boost/python/has_back_reference.hpp>
#include <boost/python/detail/not_specified.hpp>
#include <boost/function/function0.hpp>
#include <memory>
#define BOOST_INCLUDE_MAIN
@@ -39,7 +40,7 @@ void assert_same(U* = 0, T* = 0)
template <class T, class Held, class Holder>
void assert_holder(T* = 0, Held* = 0, Holder* = 0)
{
assert_same<Holder>(boost::python::objects::select_holder<T,Held>((Held*)0).get());
assert_same<Holder>(boost::python::objects::select_holder<T,Held>::execute((Held*)0).get());
}
int test_main(int, char * [])