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:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
20
include/boost/python/object/class_detail.hpp
Normal file
20
include/boost/python/object/class_detail.hpp
Normal 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
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
45
include/boost/python/object/instance.hpp
Normal file
45
include/boost/python/object/instance.hpp
Normal 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
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
72
include/boost/python/object/make_instance.hpp
Normal file
72
include/boost/python/object/make_instance.hpp
Normal 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
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
;
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 * [])
|
||||
|
||||
Reference in New Issue
Block a user