2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-22 17:32:55 +00:00

Bug fixes in property handling

[SVN r21429]
This commit is contained in:
Dave Abrahams
2003-12-31 00:23:52 +00:00
parent 1102fec2a0
commit eedc88b56a
4 changed files with 99 additions and 29 deletions

View File

@@ -127,7 +127,6 @@ namespace detail
register_wrapper_class_impl((Held*)0, (T*)0, 0);
}
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
template <class T>
struct is_data_member_pointer
: mpl::and_<
@@ -135,15 +134,17 @@ namespace detail
, mpl::not_<is_member_function_pointer<T> >
>
{};
# define BOOST_PYTHON_DATA_MEMBER_HELPER , detail::is_data_member_pointer<D>()
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
# define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
# define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
# elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
# define BOOST_PYTHON_DATA_MEMBER_HELPER , 0
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
# define BOOST_PYTHON_YES_DATA_MEMBER , int
# define BOOST_PYTHON_NO_DATA_MEMBER , ...
# else
# define BOOST_PYTHON_DATA_MEMBER_HELPER
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
# define BOOST_PYTHON_YES_DATA_MEMBER
# define BOOST_PYTHON_NO_DATA_MEMBER
# endif
@@ -337,39 +338,39 @@ class class_ : public objects::class_base
template <class D>
self& def_readonly(char const* name, D const& d)
{
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D const& d)
{
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readonly(char const* name, D& d)
{
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
template <class D>
self& def_readwrite(char const* name, D& d)
{
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER);
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
}
// Property creation
template <class Get>
self& add_property(char const* name, Get fget)
{
base::add_property(name, make_fn(fget));
base::add_property(name, this->make_getter(fget));
return *this;
}
template <class Get, class Set>
self& add_property(char const* name, Get fget, Set fset)
{
base::add_property(name, make_fn(fget), make_fn(fset));
base::add_property(name, this->make_getter(fget), this->make_setter(fset));
return *this;
}
@@ -415,25 +416,55 @@ class class_ : public objects::class_base
}
private: // helper functions
// Builds a method for this class around the given [member]
// function pointer or object, appropriately adjusting the type of
// the first signature argument so that if f is a member of a
// (possibly not wrapped) base class of T, an lvalue argument of
// type T will be required.
//
// @group make_fn {
// @group PropertyHelpers {
template <class F>
object make_fn(F const& f)
object make_getter(F f)
{
return make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl(
f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
);
}
template <class F>
object make_setter(F f)
{
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl(
f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
);
}
template <class F>
object make_fn_impl(F const& f, mpl::false_, void*, mpl::false_)
{
return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
}
object
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
const&
# endif
make_fn(object const& x)
template <class D, class B>
object make_fn_impl(D B::*pm_, mpl::false_, char*, mpl::true_)
{
D T::*pm = pm_;
return python::make_getter(pm);
}
template <class D, class B>
object make_fn_impl(D B::*pm_, mpl::false_, int*, mpl::true_)
{
D T::*pm = pm_;
return python::make_setter(pm);
}
template <class F>
object make_fn_impl(F const& x, mpl::true_, void*, mpl::false_)
{
return x;
}
@@ -443,30 +474,28 @@ class class_ : public objects::class_base
self& def_readonly_impl(
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
{
D T::*pm = pm_;
return this->add_property(name, make_getter(pm));
return this->add_property(name, pm_);
}
template <class D, class B>
self& def_readwrite_impl(
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
{
D T::*pm = pm_;
return this->add_property(name, make_getter(pm), make_setter(pm));
return this->add_property(name, pm_, pm_);
}
template <class D>
self& def_readonly_impl(
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, make_getter(d));
return this->add_static_property(name, python::make_getter(d));
}
template <class D>
self& def_readwrite_impl(
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
{
return this->add_static_property(name, make_getter(d), make_setter(d));
return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
}
inline void register_() const;

View File

@@ -17,8 +17,6 @@
namespace boost { namespace python { namespace api {
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
template <class X>
char is_object_operators_helper(object_operators<X> const*);
@@ -27,7 +25,7 @@ no_type is_object_operators_helper(...);
template <class X> X* make_ptr();
template <class L, class R>
template <class L, class R = L>
struct is_object_operators
{
enum {
@@ -40,6 +38,7 @@ struct is_object_operators
typedef mpl::bool_<value> type;
};
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
template <class L, class R, class T>
struct enable_binary
: boost::iterators::enable_if<is_object_operators<L,R>, T>

View File

@@ -2,6 +2,26 @@
using namespace boost::python;
namespace test {
// Hmm. return_internal_reference<>() wants to wrap a real class.
class ret_type
{
public:
ret_type() : i(42.5) {}
double i;
};
class crash_me
{
private:
ret_type i;
public:
ret_type& get_i() { return i; }
};
}
struct X
{
X( int value ) : m_value( value )
@@ -55,6 +75,20 @@ BOOST_PYTHON_MODULE(properties_ext)
make_setter( &X::s_count, return_by_internal_reference_t() ) )
//defining class property using a global function
.add_static_property( "instance_count_injected", &get_X_instance_count );
class_< test::ret_type>( "ret_type")
.add_property( "i", &test::ret_type::i, &test::ret_type::i)
;
class_< test::crash_me> crash_me_wrapper( "crash_me");
crash_me_wrapper
.def( "get_i", &test::crash_me::get_i , return_internal_reference<>())
;
crash_me_wrapper.add_property( "i", crash_me_wrapper.attr("get_i"));
}
#include "module_tail.cpp"

View File

@@ -1,5 +1,13 @@
"""
This is test module for properies.
This is test module for properties.
>>> r = properties.ret_type()
>>> r.i = 22.5
>>> r.i
22.5
>>> c = properties.crash_me()
>>> c.i.i
42.5
>>> X = properties.X