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

object_core.hpp - allow wrapping of objects which take object managers in their constructors.

forward.hpp
pointer_holder.hpp
value_holder.hpp
test/long.[py/cpp]

pointee.hpp,    - begin making borland work.
cv_category.hpp,
referent_storage.hpp
instance.hpp

self.hpp        - removed flotsam

signature.hpp   - use vector instead of list

destroy.hpp     - removed needless complication

make_keyword_range_fn.hpp - support for simpler init using vectors

class_converters.hpp - workaround for pro7

inheritance.hpp - simplified; took out pro7 workarounds; factored out
                  inheritance_query.hpp to reduce recompilation
                  dependencies

make_ptr_instance.hpp - add missing typename

registry.cpp    - add a little invariant checking for metrowerks

class.cpp       - stopped relying on class_id typedef

test/data_members.cpp - added a few more tests to make sure things compile at least.
test/destroy_test.cpp - removed cheating has_trivial_destructor tests
test/enum.cpp         - added some pro7 workarounds
test/virtual_functions.[py/cpp] - added _some_ tests for callbacks which return by reference.


[SVN r18489]
This commit is contained in:
Dave Abrahams
2003-05-21 22:17:23 +00:00
parent 66d6272942
commit 43e5ccd0a7
25 changed files with 302 additions and 171 deletions

View File

@@ -24,9 +24,12 @@ typedef cv_tag<true,true> const_volatile_;
template <class T>
struct cv_category
{
BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value);
BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value);
typedef cv_tag<c,v> type;
// BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value);
// BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value);
typedef cv_tag<
::boost::is_const<T>::value
, ::boost::is_volatile<T>::value
> type;
};
}}} // namespace boost::python::detail

View File

@@ -6,15 +6,14 @@
#ifndef DESTROY_DWA2002221_HPP
# define DESTROY_DWA2002221_HPP
# include <boost/type_traits/composite_traits.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/type_traits/is_array.hpp>
namespace boost { namespace python { namespace detail {
template <bool array, bool trivial_destructor> struct value_destroyer;
template <bool array> struct value_destroyer;
template <>
struct value_destroyer<false,false>
struct value_destroyer<false>
{
template <class T>
static void execute(T const volatile* p)
@@ -24,16 +23,17 @@ struct value_destroyer<false,false>
};
template <>
struct value_destroyer<true,false>
struct value_destroyer<true>
{
template <class A, class T>
static void execute(A*, T const volatile* const first)
{
for (T const volatile* p = first; p != first + sizeof(A)/sizeof(T); ++p)
{
value_destroyer<
boost::is_array<T>::value
,boost::has_trivial_destructor<T>::value
>::execute(p);
>::execute(p);
}
}
template <class T>
@@ -43,24 +43,6 @@ struct value_destroyer<true,false>
}
};
template <>
struct value_destroyer<true,true>
{
template <class T>
static void execute(T const volatile*)
{
}
};
template <>
struct value_destroyer<false,true>
{
template <class T>
static void execute(T const volatile*)
{
}
};
template <class T>
inline void destroy_referent_impl(void* p, T& (*)())
{
@@ -68,8 +50,7 @@ inline void destroy_referent_impl(void* p, T& (*)())
// must come *before* T for metrowerks
value_destroyer<
(boost::is_array<T>::value)
,(boost::has_trivial_destructor<T>::value)
>::execute((const volatile T*)p);
>::execute((const volatile T*)p);
}
template <class T>

View File

@@ -34,17 +34,15 @@ object make_keyword_range_function(F f, Policies const& policies, keyword_range
// constructor.
//
// Holder and ArgList are intended to be explicitly specified.
template <class ArgList, class Holder, class CallPolicies>
template <class ArgList, class Arity, class Holder, class CallPolicies>
object make_keyword_range_constructor(
CallPolicies const& policies // The CallPolicies with which to invoke the Holder's constructor
, detail::keyword_range const& kw // The (possibly empty) set of associated argument keywords
, Holder* = 0
, ArgList* = 0)
, ArgList* = 0, Arity* = 0)
{
BOOST_STATIC_CONSTANT(unsigned, arity = mpl::size<ArgList>::value);
return detail::make_keyword_range_function(
objects::make_holder<arity>
objects::make_holder<Arity::value>
::template apply<Holder,ArgList>::execute
, policies
, kw);

View File

@@ -67,7 +67,9 @@ union aligned_storage
template <class T>
struct referent_storage
{
typedef aligned_storage<referent_size<T>::value> type;
typedef aligned_storage<
::boost::python::detail::referent_size<T>::value
> type;
};
}}} // namespace boost::python::detail

View File

@@ -14,6 +14,7 @@
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/type_traits/add_pointer.hpp>
# include <boost/type_traits/is_polymorphic.hpp>
# include <boost/mpl/for_each.hpp>
@@ -58,11 +59,15 @@ struct register_base_of
register_conversion<Derived,Base>(false);
// Register the down-cast, if appropriate.
mpl::if_c<
is_polymorphic<Base>::value
, register_downcast<Base,Derived>
, do_nothing
>::type::execute();
mpl::if_<
# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
mpl::true_
# else
is_polymorphic<Base>
# endif
, register_downcast<Base,Derived>
, do_nothing
>::type::execute();
}
};

View File

@@ -7,10 +7,9 @@
# define FORWARD_DWA20011215_HPP
# include <boost/mpl/if.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/is_scalar.hpp>
# include <boost/type_traits/add_const.hpp>
# include <boost/type_traits/add_reference.hpp>
# include <boost/ref.hpp>
namespace boost { namespace python { namespace objects {
@@ -24,7 +23,7 @@ struct reference_to_value
typedef typename add_reference<typename add_const<T>::type>::type reference;
reference_to_value(reference x) : m_value(x) {}
operator reference() const { return m_value; }
reference get() const { return m_value; }
private:
reference m_value;
};
@@ -34,27 +33,43 @@ struct reference_to_value
// is T.
template <class T>
struct forward
: mpl::if_c<
is_scalar<T>::value
: mpl::if_<
is_scalar<T>
, T
, reference_to_value<T> >
, reference_to_value<T>
>
{
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
class unforward
struct unforward
{
public:
typedef typename unwrap_reference<T>::type& type;
};
template<typename T>
class unforward<reference_to_value<T> >
struct unforward<reference_to_value<T> >
{
public:
typedef T type;
};
template <typename T>
struct unforward_cref
: add_reference<
typename add_const<
typename unwrap_reference<T>::type
>::type
>
{
};
template<typename T>
struct unforward_cref<reference_to_value<T> >
: add_reference<typename add_const<T>::type>
{
};
# else // no partial specialization
namespace detail
@@ -87,26 +102,81 @@ namespace detail
};
};
template<typename T>
class is_reference_to_value
template<bool wrapped = false>
struct cref_unforwarder
{
template <class T>
struct apply
: add_reference<
typename add_const<
typename unwrap_reference<T>::type
>::type
>
{
};
};
template<>
struct cref_unforwarder<true>
{
template <class T>
struct apply
: add_reference<
typename add_const<
typename T::reference
>::type
>
{
};
};
template<typename T>
struct is_reference_to_value
{
public:
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(is_reference_to_value_test(boost::type<T>()))
== sizeof(yes_reference_to_value_t)));
typedef mpl::bool_<value> type;
};
}
template <typename T>
class unforward
struct unforward
: public detail::unforwarder<
detail::is_reference_to_value<T>::value
>::template apply<T>
{};
template <typename T>
struct unforward_cref
: public detail::cref_unforwarder<
detail::is_reference_to_value<T>::value
>::template apply<T>
{};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
typename reference_to_value<T>::reference
do_unforward(reference_to_value<T> const& x, int)
{
return x.get();
}
template <class T>
typename reference_wrapper<T>::type&
do_unforward(reference_wrapper<T> const& x, int)
{
return x.get();
}
template <class T>
T const& do_unforward(T const& x, ...)
{
return x;
}
}}} // namespace boost::python::objects
#endif // FORWARD_DWA20011215_HPP

View File

@@ -26,11 +26,7 @@ BOOST_PYTHON_DECL void register_dynamic_id_aux(
class_id static_id, dynamic_id_function get_dynamic_id);
BOOST_PYTHON_DECL void add_cast(
class_id src_t, class_id dst_t, void* (*cast)(void*), bool polymorphic);
BOOST_PYTHON_DECL void* find_static_type(void* p, class_id src, class_id dst);
BOOST_PYTHON_DECL void* find_dynamic_type(void* p, class_id src, class_id dst);
class_id src_t, class_id dst_t, void* (*cast)(void*), bool is_downcast);
//
// a generator with an execute() function which, given a source type
@@ -62,12 +58,12 @@ struct non_polymorphic_id_generator
// Now the generalized selector
template <class T>
struct dynamic_id_generator
{
typedef typename mpl::if_c<
is_polymorphic<T>::value
, polymorphic_id_generator<T>
, non_polymorphic_id_generator<T> >::type type;
};
: mpl::if_<
boost::is_polymorphic<T>
, boost::python::objects::polymorphic_id_generator<T>
, boost::python::objects::non_polymorphic_id_generator<T>
>
{};
// Register the dynamic id function for T with the type-conversion
// system.
@@ -108,45 +104,28 @@ struct implicit_cast_generator
template <class Source, class Target>
struct cast_generator
: mpl::if_<
is_base_and_derived<Target,Source>
, implicit_cast_generator<Source,Target>
, dynamic_cast_generator<Source,Target>
>
{
// It's OK to return false, since we can always cast up with
// dynamic_cast<> if neccessary.
# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
BOOST_STATIC_CONSTANT(bool, is_upcast = false);
# else
BOOST_STATIC_CONSTANT(
bool, is_upcast = (
is_base_and_derived<Target,Source>::value
));
# endif
typedef typename mpl::if_c<
is_upcast
# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
// grab a few more implicit_cast cases for CodeWarrior
|| !is_polymorphic<Source>::value
|| !is_polymorphic<Target>::value
# endif
, implicit_cast_generator<Source,Target>
, dynamic_cast_generator<Source,Target>
>::type type;
};
template <class Source, class Target>
inline void register_conversion(
// We need this parameter because CWPro7 can't determine
// which is the base reliably.
bool is_downcast = !cast_generator<Source,Target>::is_upcast
// These parameters shouldn't be used, they're an MSVC bug workaround
bool is_downcast = ::boost::is_base_and_derived<Source,Target>::value
// These parameters shouldn't be used; they're an MSVC bug workaround
, Source* = 0, Target* = 0)
{
typedef typename cast_generator<Source,Target>::type generator;
add_cast(python::type_id<Source>()
, python::type_id<Target>()
, &generator::execute
, is_downcast);
add_cast(
python::type_id<Source>()
, python::type_id<Target>()
, &generator::execute
, is_downcast
);
}
}}} // namespace boost::python::object

View File

@@ -0,0 +1,18 @@
// Copyright David Abrahams 2003. 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 INHERITANCE_QUERY_DWA2003520_HPP
# define INHERITANCE_QUERY_DWA2003520_HPP
# include <boost/python/type_id.hpp>
namespace boost { namespace python { namespace objects {
BOOST_PYTHON_DECL void* find_static_type(void* p, type_info src, type_info dst);
BOOST_PYTHON_DECL void* find_dynamic_type(void* p, type_info src, type_info dst);
}}} // namespace boost::python::object
#endif // INHERITANCE_QUERY_DWA2003520_HPP

View File

@@ -26,8 +26,9 @@ struct instance
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;
typedef typename type_with_alignment<
::boost::alignment_of<Data>::value
>::type align_t;
union
{

View File

@@ -37,7 +37,9 @@ struct make_ptr_instance
if (p == 0)
return 0;
PyTypeObject* derived = get_derived_class_object(is_polymorphic<U>::type(), p);
PyTypeObject* derived = get_derived_class_object(
BOOST_DEDUCED_TYPENAME is_polymorphic<U>::type(), p);
if (derived)
return derived;
return converter::registered<T>::converters.get_class_object();

View File

@@ -13,7 +13,7 @@
# include <boost/python/instance_holder.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/object/inheritance.hpp>
# include <boost/python/object/inheritance_query.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/python/pointee.hpp>
# include <boost/python/detail/force_instantiate.hpp>
@@ -43,7 +43,11 @@ bool is_null(T* p, int)
return p == 0;
}
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)(a##n)
# if BOOST_WORKAROUND(__GNUC__, == 2)
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)objects::do_unforward(a##n,0)
# else
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) objects::do_unforward(a##n,0)
# endif
template <class Pointer, class Value>
struct pointer_holder : instance_holder

View File

@@ -14,7 +14,7 @@
# include <boost/python/instance_holder.hpp>
# include <boost/python/type_id.hpp>
# include <boost/python/object/inheritance.hpp>
# include <boost/python/object/inheritance_query.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/python/detail/force_instantiate.hpp>
@@ -31,7 +31,11 @@
namespace boost { namespace python { namespace objects {
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)(a##n)
# if BOOST_WORKAROUND(__GNUC__, == 2)
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)objects::do_unforward(a##n,0)
# else
# define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) objects::do_unforward(a##n,0)
# endif
template <class Held>
struct value_holder : instance_holder

View File

@@ -12,12 +12,15 @@
# include <boost/python/handle_fwd.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/slice_nil.hpp>
# include <boost/python/detail/raw_pyobject.hpp>
# include <boost/python/refcount.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/tag.hpp>
# include <boost/python/detail/raw_pyobject.hpp>
# include <boost/python/detail/dependent.hpp>
# include <boost/python/object/forward.hpp>
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/debug/line.hpp>
@@ -81,7 +84,7 @@ namespace api
};
# endif
template <bool is_proxy, bool is_object_manager> struct object_initializer;
template <class T> struct object_initializer;
class object;
typedef PyObject* (object::*bool_type)() const;
@@ -211,19 +214,35 @@ namespace api
public:
// default constructor creates a None object
object();
// explicit conversion from any C++ object to Python
template <class T>
explicit object(T const& x)
: object_base(
object_initializer<
is_proxy<T>::value
, converter::is_object_manager<T>::value
>::get(&x, detail::convertible<object const*>::check(&x)))
: object_base(
object_initializer<
BOOST_DEDUCED_TYPENAME unwrap_reference<T>::type
>::get(
do_unforward(x)
, detail::convertible<object const*>::check(
to_ptr(
do_unforward(x)
)
)
))
{
}
// Throw error_already_set() if the handle is null.
BOOST_PYTHON_DECL explicit object(handle<> const&);
private:
template <class T>
static T const* to_ptr(T const&) { return 0; }
template <class T>
typename objects::unforward_cref<T>::type do_unforward(T const& x)
{
return x;
}
public: // implementation detail -- for internal use only
explicit object(detail::borrowed_reference);
@@ -264,47 +283,55 @@ namespace api
// based on whether T is a proxy or derived from object
//
template <bool is_proxy = false, bool is_object_manager = false>
struct object_initializer
struct object_initializer_impl
{
static PyObject*
get(object const* x, detail::yes_convertible)
get(object const& x, detail::yes_convertible)
{
return python::incref(x->ptr());
return python::incref(x.ptr());
}
template <class T>
static PyObject*
get(T const* x, detail::no_convertible)
get(T const& x, detail::no_convertible)
{
return python::incref(converter::arg_to_python<T>(*x).get());
return python::incref(converter::arg_to_python<T>(x).get());
}
};
template <>
struct object_initializer<true, false>
struct object_initializer_impl<true, false>
{
template <class Policies>
static PyObject*
get(proxy<Policies> const* x, detail::no_convertible)
get(proxy<Policies> const& x, detail::no_convertible)
{
return python::incref(x->operator object().ptr());
return python::incref(x.operator object().ptr());
}
};
template <>
struct object_initializer<false, true>
struct object_initializer_impl<false, true>
{
template <class T>
static PyObject*
get(T const* x, ...)
get(T const& x, ...)
{
return python::incref(get_managed_object(*x, tag));
return python::incref(get_managed_object(x, tag));
}
};
template <>
struct object_initializer<true, true>
struct object_initializer_impl<true, true>
{}; // empty implementation should cause an error
template <class T>
struct object_initializer : object_initializer_impl<
is_proxy<T>::value
, converter::is_object_manager<T>::value
>
{};
}
using api::object;
template <class T> struct extract;

View File

@@ -31,7 +31,9 @@ namespace detail
template <class T>
struct pointee
: detail::pointee_impl<is_pointer<T>::value>::template apply<T>
: detail::pointee_impl<
::boost::is_pointer<T>::value
>::template apply<T>
{
};

View File

@@ -10,9 +10,7 @@
namespace boost { namespace python {
//# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
# define BOOST_PYTHON_SELF_IS_CLASS
//# endif
#define BOOST_PYTHON_SELF_IS_CLASS
// Sink self_t into its own namespace so that we have a safe place to
// put the completely general operator templates which operate on

View File

@@ -27,7 +27,7 @@
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
# define BOOST_PYTHON_LIST_INC(n) \
BOOST_PP_CAT(mpl::list, BOOST_PP_INC(n))
BOOST_PP_CAT(mpl::vector, BOOST_PP_INC(n))
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace python { namespace detail {

View File

@@ -92,10 +92,16 @@ namespace // <unnamed>
std::cout << "looking up " << type
<< (p == entries().end() || p->target_type != type
? "...NOT found\n" : "...found\n");
# endif
return const_cast<entry*>(
&*entries().insert(entry(type)).first
);
# endif
std::pair<registry_t::const_iterator,bool> pos_ins
= entries().insert(entry(type));
# if __MWERKS__ >= 0x3000
// do a little invariant checking if a change was made
if ( pos_ins.second )
assert(entries().invariants());
# endif
return const_cast<entry*>(&*pos_ins.first);
}
} // namespace <unnamed>

View File

@@ -437,7 +437,7 @@ namespace objects
{
// Find a registered class object corresponding to id. Return a
// null handle if no such class is registered.
inline type_handle query_class(class_id id)
inline type_handle query_class(type_info id)
{
converter::registration const* p = converter::registry::query(id);
return type_handle(
@@ -448,7 +448,7 @@ namespace objects
// Find a registered class corresponding to id. If not found,
// throw an appropriate exception.
type_handle get_class(class_id id)
type_handle get_class(type_info id)
{
type_handle result(query_class(id));
@@ -473,7 +473,7 @@ namespace objects
// rest corresponding to its declared bases.
//
inline object
new_class(char const* name, std::size_t num_types, class_id const* const types, char const* doc)
new_class(char const* name, std::size_t num_types, type_info const* const types, char const* doc)
{
assert(num_types >= 1);
@@ -510,7 +510,7 @@ namespace objects
}
class_base::class_base(
char const* name, std::size_t num_types, class_id const* const types, char const* doc)
char const* name, std::size_t num_types, type_info const* const types, char const* doc)
: object(new_class(name, num_types, types, doc))
{
// Insert the new class object in the registry
@@ -630,7 +630,7 @@ namespace objects
));
}
BOOST_PYTHON_DECL type_handle registered_class_object(class_id id)
BOOST_PYTHON_DECL type_handle registered_class_object(type_info id)
{
return query_class(id);
}

View File

@@ -51,6 +51,35 @@ struct Var : VarBase
int Var::static1 = 0;
Y Var::static2(0);
// Compilability regression tests
namespace
{
struct trivial
{
trivial() : value(123) {}
double value;
};
struct Color3
{
static const Color3 black;
};
const Color3 Color3::black;
void compilability_test()
{
class_<trivial>("trivial")
.add_property("property", make_getter(&trivial::value, return_value_policy<return_by_value>()))
.def_readonly("readonly", &trivial::value)
;
class_< Color3 >("Color3", init< const Color3 & >())
.def_readonly("BLACK", &Color3::black) // line 17
;
}
}
BOOST_PYTHON_MODULE(data_members_ext)
{
class_<X>("X", init<int>())

View File

@@ -1,19 +1,6 @@
#include <boost/python/detail/destroy.hpp>
#include <cassert>
struct bar;
namespace boost
{
// lie to the library about bar so we can show that its destructor is optimized away.
template <>
struct has_trivial_destructor<bar>
{
BOOST_STATIC_CONSTANT(bool, value=true);
};
}
int count;
int marks[] = {
-1
@@ -33,8 +20,6 @@ struct foo
int n;
};
struct bar : foo {};
void assert_destructions(int n)
{
for (int i = 0; i < n; ++i)
@@ -62,20 +47,5 @@ int main()
boost::python::detail::destroy_referent<y&>(f3);
assert_destructions(7);
bar* b1 = new bar;
boost::python::detail::destroy_referent<bar&>(b1);
assert_destructions(7);
bar* b2 = new bar[2];
typedef bar xb[2];
boost::python::detail::destroy_referent<xb&>(b2);
assert_destructions(7);
typedef bar yb[2][2];
xb* b3 = new yb;
boost::python::detail::destroy_referent<yb&>(b3);
assert_destructions(7);
return 0;
}

View File

@@ -40,9 +40,16 @@ BOOST_PYTHON_MODULE(enum_ext)
def("identity", identity_);
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
color colorized::*px = &colorized::x;
class_<colorized>("colorized")
.def_readwrite("x", px)
;
#else
class_<colorized>("colorized")
.def_readwrite("x", &colorized::x)
;
#endif
}
#include "module_tail.cpp"

View File

@@ -7,6 +7,7 @@
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/long.hpp>
#include <boost/python/class.hpp>
#include <cassert>
using namespace boost::python;
@@ -39,6 +40,14 @@ int is_long2(char const*)
return 0;
}
// tests for accepting objects (and derived classes) in constructors
// from "Milind Patil" <milind_patil-at-hotmail.com>
struct Y
{
Y(boost::python::long_) {}
};
BOOST_PYTHON_MODULE(long_ext)
{
def("new_long", new_long);
@@ -46,6 +55,8 @@ BOOST_PYTHON_MODULE(long_ext)
def("longify_string", longify_string);
def("is_long", is_long1);
def("is_long", is_long2);
class_< Y >("Y", init< boost::python::long_ >())
;
}

View File

@@ -10,6 +10,8 @@
'yes'
>>> is_long('20')
0
>>> x = Y(4294967295)
'''
def run(args = None):

View File

@@ -6,6 +6,7 @@
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/return_internal_reference.hpp>
#include <boost/python/call_method.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>
@@ -39,6 +40,8 @@ struct abstract : X
abstract(int x) : X(x) {};
int call_f(Y const& y) { return f(y); }
virtual int f(Y const& y) = 0;
abstract& call_g(Y const& y) { return g(y); }
virtual abstract& g(Y const& y) = 0;
};
struct concrete : X
@@ -59,6 +62,11 @@ struct abstract_callback : abstract
return call_method<int>(self, "f", boost::ref(y));
}
abstract& g(Y const& y)
{
return call_method<abstract&>(self, "g", boost::ref(y));
}
PyObject* self;
};
@@ -101,6 +109,7 @@ BOOST_PYTHON_MODULE(virtual_functions_ext)
.def("value", &abstract::value)
.def("call_f", &abstract::call_f)
.def("call_g", &abstract::call_g, return_internal_reference<>())
.def("set", &abstract::set)
;

View File

@@ -11,6 +11,8 @@
>>> class A1(abstract):
... def f(self, y):
... return y.value() * 2
... def g(self, y):
... return self
>>> class A2(abstract):
... pass
@@ -22,15 +24,16 @@
#
# Test abstract with f overridden
# Test abstract with f,g overridden
#
>>> a1 = A1(42)
>>> a1.value()
42
# Call f indirectly from C++
# Call f,g indirectly from C++
>>> a1.call_f(y1)
32
>>> assert type(a1.call_g(y1)) is abstract
# Call f directly from Python
>>> a1.f(y2)