Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r62193 - in sandbox/python_extensions: . boost/python boost/python/const_aware libs/python/src libs/python/test
From: talljimbo_at_[hidden]
Date: 2010-05-25 04:50:10


Author: jbosch
Date: 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
New Revision: 62193
URL: http://svn.boost.org/trac/boost/changeset/62193

Log:
boost.python extensions - partial rewrite of const_aware, using proxy classes: public interface is much simpler, conversions for shared_ptr can now be automatic, and from_python conversions now preserve const-correctness. Requires building separate shared library.
Added:
   sandbox/python_extensions/TODO (contents, props changed)
   sandbox/python_extensions/boost/python/const_aware/
   sandbox/python_extensions/boost/python/const_aware.hpp
      - copied, changed from r62162, /sandbox/python_extensions/boost/python/const_aware_class.hpp
   sandbox/python_extensions/boost/python/const_aware/as_const.hpp (contents, props changed)
   sandbox/python_extensions/boost/python/const_aware/const_shared_ptr_to_python.hpp (contents, props changed)
   sandbox/python_extensions/boost/python/const_aware/exposer.hpp
      - copied, changed from r62162, /sandbox/python_extensions/boost/python/const_aware_class.hpp
   sandbox/python_extensions/boost/python/const_aware/proxy_class.hpp (contents, props changed)
   sandbox/python_extensions/boost/python/const_aware/proxy_class_fwd.hpp (contents, props changed)
   sandbox/python_extensions/boost/python/const_aware/proxy_method.hpp (contents, props changed)
   sandbox/python_extensions/boost/python/const_aware/registry.hpp
      - copied, changed from r62162, /sandbox/python_extensions/boost/python/const_aware_class.hpp
   sandbox/python_extensions/boost/python/const_aware/rvalue_from_proxy.hpp (contents, props changed)
   sandbox/python_extensions/boost/python/const_aware/shared_ptr_from_proxy.hpp (contents, props changed)
   sandbox/python_extensions/libs/python/src/ (props changed)
   sandbox/python_extensions/libs/python/src/SConscript
      - copied, changed from r62136, /sandbox/numpy/libs/python/numpy/src/SConscript
   sandbox/python_extensions/libs/python/src/proxy_class.cpp
      - copied, changed from r62162, /sandbox/python_extensions/libs/python/test/const_aware.cpp
   sandbox/python_extensions/libs/python/src/proxy_method.cpp
      - copied, changed from r62162, /sandbox/python_extensions/libs/python/test/const_aware.cpp
   sandbox/python_extensions/libs/python/src/registry.cpp
      - copied, changed from r62162, /sandbox/python_extensions/libs/python/test/const_aware.cpp
Removed:
   sandbox/python_extensions/boost/python/const_aware_class.hpp
Text files modified:
   sandbox/python_extensions/README | 20 +
   sandbox/python_extensions/SConstruct | 8
   sandbox/python_extensions/boost/python/const_aware.hpp | 418 +--------------------------------------
   sandbox/python_extensions/boost/python/const_aware/exposer.hpp | 235 +++++----------------
   sandbox/python_extensions/boost/python/const_aware/registry.hpp | 408 +-------------------------------------
   sandbox/python_extensions/libs/python/src/SConscript | 4
   sandbox/python_extensions/libs/python/src/proxy_class.cpp | 383 ++++++++++++++++++++++++++++++++----
   sandbox/python_extensions/libs/python/src/proxy_method.cpp | 240 +++++++++++++++++-----
   sandbox/python_extensions/libs/python/src/registry.cpp | 76 +-----
   sandbox/python_extensions/libs/python/test/SConscript | 3
   sandbox/python_extensions/libs/python/test/const_aware.cpp | 82 ++++---
   sandbox/python_extensions/libs/python/test/const_aware.py | 78 ++++++-
   12 files changed, 766 insertions(+), 1189 deletions(-)

Modified: sandbox/python_extensions/README
==============================================================================
--- sandbox/python_extensions/README (original)
+++ sandbox/python_extensions/README 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -24,16 +24,28 @@
  - boost::shared_ptr<T const> conversions that work simply by
    casting away constness ('to_python/const_cast_shared_ptr.hpp').
 
+ - Wrapping classes in a const_correct manner ('const_aware'), by
+ creating a const proxy class with a subset of the methods and
+ properties of the master class. Const proxies can be
+ automatically generated from shared_ptr<T const> return values,
+ or generated explicitly by using the as_const<> call policies.
+ See the const_aware test code for an example (yes, better
+ documentation is needed).
 
 INSTALLATION
 
-All the libraries are header only, and the SCons-based build system
-is only used to run tests (and it doesn't try very hard to locate
-Boost.Python if that's non-trivial on your system.
+Most of the extensions (the exception is the const_aware package)
+are header only, and can be used simply by including the
+appropriate files. The simple SCons build system is mostly intended
+to be used just to run tests (and it doesn't try very hard to locate
+Boost.Python if that's non-trivial on your system).
 
 While I have only tested these on gcc 4.4 in Linux, I don't have
 any reason to think they won't work on any other platform with
-a modern C++ compiler.
+a modern C++ compiler, though I'm not an expert on the differences
+in dynamic linking and symbol visibility on different platforms,
+and those might cause a problem for const_aware. I'd be curious
+to hear of any successes and/or failures.
 
 As of this writing (May 2010), the latest version of this code
 is in the boost sandbox at

Modified: sandbox/python_extensions/SConstruct
==============================================================================
--- sandbox/python_extensions/SConstruct (original)
+++ sandbox/python_extensions/SConstruct 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -5,4 +5,12 @@
 bp_extensions_env.Append(CPPPATH = "#")
 
 Export("bp_extensions_env")
+lib = SConscript("libs/python/src/SConscript")
+libpath = os.path.abspath("libs/python/src")
+if os.environ.has_key("LD_LIBRARY_PATH"):
+ bp_extensions_env["ENV"]["LD_LIBRARY_PATH"] = "%s:%s" % (libpath, os.environ["LD_LIBRARY_PATH"])
+else:
+ bp_extensions_env["ENV"]["LD_LIBRARY_PATH"] = libpath
+bp_extensions_env.Append(LIBPATH="#libs/python/src")
+
 SConscript("libs/python/test/SConscript")

Added: sandbox/python_extensions/TODO
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/TODO 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,8 @@
+const_aware:
+ - check for in-Python construction of proxies (maybe needs to be disabled with something like no_init)
+ - smarter shared_ptr converter registration (take held_type into account)
+ - test subclasses and back-reference wrappers
+ - documentation!
+
+to_python:
+ - create rvalue converters corresponding to copy_to_XXX policies

Copied: sandbox/python_extensions/boost/python/const_aware.hpp (from r62162, /sandbox/python_extensions/boost/python/const_aware_class.hpp)
==============================================================================
--- /sandbox/python_extensions/boost/python/const_aware_class.hpp (original)
+++ sandbox/python_extensions/boost/python/const_aware.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,403 +1,23 @@
-#ifndef BOOST_PYTHON_CONST_AWARE_CLASS_HPP
-#define BOOST_PYTHON_CONST_AWARE_CLASS_HPP
+#ifndef BOOST_PYTHON_CONST_AWARE_HPP
+#define BOOST_PYTHON_CONST_AWARE_HPP
 
 #include <boost/python.hpp>
-#include <boost/function_types/parameter_types.hpp>
-#include <boost/mpl/front.hpp>
-#include <boost/type_traits/is_const.hpp>
-#include <boost/type_traits/remove_reference.hpp>
-#include <boost/static_assert.hpp>
+#include <boost/python/const_aware/exposer.hpp>
+#include <boost/python/const_aware/as_const.hpp>
+#include <boost/python/const_aware/const_shared_ptr_to_python.hpp>
+#include <boost/python/const_aware/shared_ptr_from_proxy.hpp>
+
+namespace boost { namespace python {
+
+template <typename W, typename X1, typename X2, typename X3>
+inline const_aware::exposer<W,X1,X2,X3> make_const_aware(
+ class_<W,X1,X2,X3> & class_ref,
+ char const * proxy_name,
+ char const * proxy_doc = 0
+) {
+ return const_aware::exposer<W,X1,X2,X3>(class_ref, proxy_name, proxy_doc);
+}
 
-namespace boost {
-namespace python {
+}} // namespace boost::python
 
-namespace const_aware_registry {
-
-BOOST_PYTHON_DECL PyTypeObject * lookup(PyTypeObject * non_const);
-
-BOOST_PYTHON_DECL void insert(object const & non_const, object const & const_);
-
-} // namespace boost::python::const_aware_registry
-
-namespace objects {
-
-template <typename T, typename Holder>
-struct make_const_ptr_instance
- : make_instance_impl<T, Holder, make_const_ptr_instance<T,Holder> >
-{
-
- template <typename Arg>
- static inline Holder* construct(void* storage, PyObject*, Arg& x) {
- return new (storage) Holder(x);
- }
-
- template <typename Ptr>
- static inline PyTypeObject* get_class_object(Ptr const& x) {
- PyTypeObject * non_const = make_ptr_instance<T,Holder>::get_class_object(x);
- return const_aware_registry::lookup(non_const);
- }
-
-#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
- static inline PyTypeObject const* get_pytype()
- {
- return converter::registered<T>::converters.get_class_object();
- }
-#endif
-};
-
-} // namespace boost::python::objects
-
-namespace detail {
-
-template <typename F>
-struct is_const_method : public
-boost::is_const<
- typename boost::remove_reference<
- typename boost::mpl::front<
- boost::function_types::parameter_types<F>
- >::type
- >::type
- >
-{};
-
-struct make_const_reference_holder {
-
- template <typename T>
- static PyObject * execute(T* p) {
- typedef objects::pointer_holder<T*,T> holder_t;
- T* q = const_cast<T*>(p);
- return objects::make_const_ptr_instance<T, holder_t>::execute(q);
- }
-
-};
-
-} // namespace boost::python::detail
-
-struct const_reference_existing_object {
-
- template <class T>
- struct apply
- {
- BOOST_STATIC_CONSTANT(
- bool, ok = is_pointer<T>::value || is_reference<T>::value);
-
- typedef typename mpl::if_c<
- ok
- , to_python_indirect<T, detail::make_const_reference_holder>
- , detail::reference_existing_object_requires_a_pointer_or_reference_return_type<T>
- >::type type;
- };
-
-};
-
-template <std::size_t owner_arg = 1, class BasePolicy_ = default_call_policies>
-struct return_internal_const_reference
- : with_custodian_and_ward_postcall<0, owner_arg, BasePolicy_>
-{
- private:
- BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0);
- public:
- typedef typename mpl::if_c<
- legal
- , const_reference_existing_object
- , detail::return_internal_reference_owner_arg_must_be_greater_than_zero<owner_arg>
- >::type result_converter;
-};
-
-template <
- typename W,
- typename X1 = detail::not_specified,
- typename X2 = detail::not_specified,
- typename X3 = detail::not_specified
- >
-class const_aware_class {
-public:
-
- typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
- typedef const_aware_class<W,X1,X2,X3> self;
-
- typedef class_<W,X1,X2,X3> const_class_t;
- typedef class_< W, typename metadata::held_type_arg, typename metadata::bases, boost::noncopyable
- > non_const_class_t;
-
- const_class_t const_class;
- non_const_class_t non_const_class;
-
-public: // constructors
-
- const_aware_class(char const * non_const_name, char const * const_name, char const* doc = 0) :
- const_class(const_name, doc), non_const_class(non_const_name, doc) { _register(); }
-
- const_aware_class(char const * non_const_name, char const * const_name, no_init_t n) :
- const_class(const_name, n), non_const_class(non_const_name, n) { _register(); }
-
- const_aware_class(char const * non_const_name, char const * const_name, char const * doc, no_init_t n) :
- const_class(const_name, doc, n), non_const_class(non_const_name, doc, n) { _register(); }
-
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name, init_base<DerivedT> const & i) :
- const_class(const_name, i), non_const_class(non_const_name, i) { _register(); }
-
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name,
- char const * doc, init_base<DerivedT> const & i) :
- const_class(const_name, doc, i), non_const_class(non_const_name, doc, i) { _register(); }
-
-public: // member functions
-
- // Generic visitation
- template <class Derived>
- self& def(def_visitor<Derived> const& visitor)
- {
- visitor.visit(non_const_class);
- visitor.visit(const_class);
- return *this;
- }
-
- // Wrap a member function or a non-member function which can take
- // a T, T cv&, or T cv* as its first parameter, a callable
- // python object, or a generic visitor.
- template <class F>
- self& def(char const* name, F f)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, f, detail::def_helper<char const*>(0), &f);
- return *this;
- }
-
- template <class A1, class A2>
- self& def(char const* name, A1 a1, A2 const& a2)
- {
- this->def_maybe_overloads(name, a1, a2, &a2);
- return *this;
- }
-
- template <class Fn, class A1, class A2>
- self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
- {
- // The arguments are definitely:
- // def(name, function, policy, doc_string)
- // def(name, function, doc_string, policy)
-
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, fn
- , detail::def_helper<A1,A2>(a1,a2)
- , &fn);
-
- return *this;
- }
-
- template <class Fn, class A1, class A2, class A3>
- self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, fn
- , detail::def_helper<A1,A2,A3>(a1,a2,a3)
- , &fn);
-
- return *this;
- }
-
-public:
-
- template <typename D>
- self & def_readonly(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readwrite(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readonly(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readwrite(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <class Get>
- self & add_property(char const* name, Get fget, char const* docstr = 0) {
- non_const_class.add_property(name, fget, docstr);
- const_class.add_property(name, fget, docstr);
- return *this;
- }
-
- template <class Get, class Set>
- self & add_property(char const* name, Get fget, Set fset, char const* docstr = 0) {
- non_const_class.add_property(name, fget, fset, docstr);
- const_class.add_property(name, fget, docstr);
- return *this;
- }
-
- template <class Get>
- self & add_static_property(char const* name, Get fget) {
- non_const_class.add_static_property(name, fget);
- const_class.add_static_property(name, fget);
- return *this;
- }
-
- template <class Get, class Set>
- self & add_static_property(char const* name, Get fget, Set fset) {
- non_const_class.add_static_property(name, fget, fset);
- const_class.add_static_property(name, fget, fset);
- return *this;
- }
-
- template <class U>
- self & setattr(char const* name, U const& x) {
- non_const_class.setattr(name, x);
- const_class.setattr(name, x);
- return *this;
- }
-
- self & enable_pickling() {
- non_const_class.enable_pickling();
- const_class.enable_pickling();
- return *this;
- }
-
- self & staticmethod(char const* name) {
- non_const_class.staticmethod(name);
- const_class.static_method(name);
- return *this;
- }
-
-private:
-
- void _register() {
- const_aware_registry::insert(non_const_class, const_class);
- }
-
- //
- // These two overloads discriminate between def() as applied to a
- // generic visitor and everything else.
- //
- // @group def_impl {
- template <class T, class Helper, class LeafVisitor, class Visitor>
- inline void def_impl(
- T*
- , char const* name
- , LeafVisitor
- , Helper const& helper
- , def_visitor<Visitor> const* v
- )
- {
- v->visit(non_const_class, name, helper);
- v->visit(const_class, name, helper);
- }
-
- template <class T, class Fn, class Helper>
- inline void def_impl(
- T*
- , char const* name
- , Fn fn
- , Helper const& helper
- , ...
- )
- {
- object method =
- make_function(
- fn
- , helper.policies()
- , helper.keywords()
- , detail::get_signature(fn, (T*)0)
- );
- objects::add_to_namespace(non_const_class, name, method, helper.doc());
-
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, method, helper.doc());
- }
-
- }
-
- //
- // These two overloads handle the definition of default
- // implementation overloads for virtual functions. The second one
- // handles the case where no default implementation was specified.
- //
- // @group def_default {
- template <class Fn, class Helper>
- inline void def_default(
- char const* name
- , Fn
- , Helper const& helper
- , mpl::bool_<true>)
- {
- detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
- helper.default_implementation());
-
- object default_method = make_function(
- helper.default_implementation(), helper.policies(), helper.keywords()
- );
-
- objects::add_to_namespace(non_const_class, name, default_method);
-
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, default_method);
- }
-
- }
-
- template <class Fn, class Helper>
- inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
- { }
- // }
-
- //
- // These two overloads discriminate between def() as applied to
- // regular functions and def() as applied to the result of
- // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
- // discriminate.
- //
- // @group def_maybe_overloads {
- template <class OverloadsT, class SigT>
- void def_maybe_overloads(
- char const* name
- , SigT sig
- , OverloadsT const& overloads
- , detail::overloads_base const*)
-
- {
- BOOST_STATIC_ASSERT(sizeof(SigT) < 0); // No support for overload macros (yet).
- }
-
- template <class Fn, class A1>
- void def_maybe_overloads(
- char const* name
- , Fn fn
- , A1 const& a1
- , ...)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name
- , fn
- , detail::def_helper<A1>(a1)
- , &fn
- );
-
- }
- // }
-};
-
-} // namespace boost::python
-} // namespace boost
-
-
-#endif // !BOOST_PYTHON_CONST_AWARE_CLASS_HPP
+#endif // !BOOST_PYTHON_CONST_AWARE_HPP

Added: sandbox/python_extensions/boost/python/const_aware/as_const.hpp
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/boost/python/const_aware/as_const.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,23 @@
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_AS_CONST_HPP
+#define BOOST_PYTHON_CONST_AWARE_AS_CONST_HPP
+
+#include <boost/python.hpp>
+#include <boost/python/const_aware/proxy_class.hpp>
+
+namespace boost { namespace python {
+
+template <typename Base = default_call_policies>
+struct as_const : Base {
+ static PyObject * postcall(PyObject *, PyObject * result) {
+ return const_aware::construct_proxy_class(result);
+ }
+};
+
+}} // namespace boost::python
+
+#endif // !BOOST_PYTHON_CONST_AWARE_AS_CONST_HPP

Added: sandbox/python_extensions/boost/python/const_aware/const_shared_ptr_to_python.hpp
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/boost/python/const_aware/const_shared_ptr_to_python.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,41 @@
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_CONST_SHARED_PTR_TO_PYTHON_HPP
+#define BOOST_PYTHON_CONST_AWARE_CONST_SHARED_PTR_TO_PYTHON_HPP
+
+#include <boost/python.hpp>
+#include <boost/python/const_aware/proxy_class.hpp>
+#include <boost/python/const_aware/registry.hpp>
+
+namespace boost { namespace python { namespace const_aware {
+
+template <typename Value>
+struct const_shared_ptr_to_python {
+ typedef typename boost::python::copy_const_reference::apply<shared_ptr<Value> const &>::type Converter;
+
+ static PyObject * convert(shared_ptr<Value const> const & source) {
+ Converter converter;
+ shared_ptr<Value> target = boost::const_pointer_cast<Value>(source);
+ PyObject * result = converter(target);
+ if (result != 0)
+ result = const_aware::construct_proxy_class(result);
+ return result;
+ }
+
+ static PyTypeObject const * get_pytype() {
+ Converter converter;
+ return const_aware::registry::query(converter.get_pytype());
+ }
+
+ const_shared_ptr_to_python() {
+ boost::python::to_python_converter<shared_ptr<Value const>, const_shared_ptr_to_python, true>();
+ }
+
+};
+
+}}} // namespace boost::python::const_aware
+
+#endif // !BOOST_PYTHON_CONST_AWARE_CONST_SHARED_PTR_TO_PYTHON_HPP

Copied: sandbox/python_extensions/boost/python/const_aware/exposer.hpp (from r62162, /sandbox/python_extensions/boost/python/const_aware_class.hpp)
==============================================================================
--- /sandbox/python_extensions/boost/python/const_aware_class.hpp (original)
+++ sandbox/python_extensions/boost/python/const_aware/exposer.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,147 +1,63 @@
-#ifndef BOOST_PYTHON_CONST_AWARE_CLASS_HPP
-#define BOOST_PYTHON_CONST_AWARE_CLASS_HPP
+// Copyright 2010 Jim Bosch
+// Adapted from Boost.Python code, Copyright David Abrahams, 2004.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_EXPOSER_HPP
+#define BOOST_PYTHON_CONST_AWARE_EXPOSER_HPP
 
 #include <boost/python.hpp>
+#include <boost/python/const_aware/proxy_class.hpp>
+#include <boost/python/const_aware/const_shared_ptr_to_python.hpp>
+#include <boost/python/const_aware/shared_ptr_from_proxy.hpp>
 #include <boost/function_types/parameter_types.hpp>
 #include <boost/mpl/front.hpp>
 #include <boost/type_traits/is_const.hpp>
 #include <boost/type_traits/remove_reference.hpp>
 #include <boost/static_assert.hpp>
 
-namespace boost {
-namespace python {
-
-namespace const_aware_registry {
-
-BOOST_PYTHON_DECL PyTypeObject * lookup(PyTypeObject * non_const);
-
-BOOST_PYTHON_DECL void insert(object const & non_const, object const & const_);
-
-} // namespace boost::python::const_aware_registry
-
-namespace objects {
-
-template <typename T, typename Holder>
-struct make_const_ptr_instance
- : make_instance_impl<T, Holder, make_const_ptr_instance<T,Holder> >
-{
-
- template <typename Arg>
- static inline Holder* construct(void* storage, PyObject*, Arg& x) {
- return new (storage) Holder(x);
- }
-
- template <typename Ptr>
- static inline PyTypeObject* get_class_object(Ptr const& x) {
- PyTypeObject * non_const = make_ptr_instance<T,Holder>::get_class_object(x);
- return const_aware_registry::lookup(non_const);
- }
-
-#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
- static inline PyTypeObject const* get_pytype()
- {
- return converter::registered<T>::converters.get_class_object();
- }
-#endif
-};
-
-} // namespace boost::python::objects
-
-namespace detail {
+namespace boost { namespace python { namespace const_aware {
 
 template <typename F>
-struct is_const_method : public
-boost::is_const<
- typename boost::remove_reference<
- typename boost::mpl::front<
- boost::function_types::parameter_types<F>
+struct is_const_method
+ : boost::is_const<
+ typename boost::remove_reference<
+ typename boost::mpl::front<
+ boost::function_types::parameter_types<F>
>::type
>::type
>
 {};
 
-struct make_const_reference_holder {
-
- template <typename T>
- static PyObject * execute(T* p) {
- typedef objects::pointer_holder<T*,T> holder_t;
- T* q = const_cast<T*>(p);
- return objects::make_const_ptr_instance<T, holder_t>::execute(q);
- }
-
-};
-
-} // namespace boost::python::detail
-
-struct const_reference_existing_object {
-
- template <class T>
- struct apply
- {
- BOOST_STATIC_CONSTANT(
- bool, ok = is_pointer<T>::value || is_reference<T>::value);
-
- typedef typename mpl::if_c<
- ok
- , to_python_indirect<T, detail::make_const_reference_holder>
- , detail::reference_existing_object_requires_a_pointer_or_reference_return_type<T>
- >::type type;
- };
-
-};
-
-template <std::size_t owner_arg = 1, class BasePolicy_ = default_call_policies>
-struct return_internal_const_reference
- : with_custodian_and_ward_postcall<0, owner_arg, BasePolicy_>
-{
- private:
- BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0);
- public:
- typedef typename mpl::if_c<
- legal
- , const_reference_existing_object
- , detail::return_internal_reference_owner_arg_must_be_greater_than_zero<owner_arg>
- >::type result_converter;
-};
-
 template <
     typename W,
     typename X1 = detail::not_specified,
     typename X2 = detail::not_specified,
     typename X3 = detail::not_specified
>
-class const_aware_class {
-public:
-
+class exposer {
+ typedef class_<W,X1,X2,X3> class_t;
+ typedef exposer<W,X1,X2,X3> self;
     typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
- typedef const_aware_class<W,X1,X2,X3> self;
-
- typedef class_<W,X1,X2,X3> const_class_t;
- typedef class_< W, typename metadata::held_type_arg, typename metadata::bases, boost::noncopyable
- > non_const_class_t;
-
- const_class_t const_class;
- non_const_class_t non_const_class;
+ typedef typename metadata::wrapped wrapped;
+ class_t & m_class;
+ proxy_class m_proxy;
 
 public: // constructors
 
- const_aware_class(char const * non_const_name, char const * const_name, char const* doc = 0) :
- const_class(const_name, doc), non_const_class(non_const_name, doc) { _register(); }
-
- const_aware_class(char const * non_const_name, char const * const_name, no_init_t n) :
- const_class(const_name, n), non_const_class(non_const_name, n) { _register(); }
+ exposer(class_t & class_ref, char const * proxy_name, char const * proxy_doc=0) :
+ m_class(class_ref), m_proxy(proxy_name, m_class, proxy_doc) {}
 
- const_aware_class(char const * non_const_name, char const * const_name, char const * doc, no_init_t n) :
- const_class(const_name, doc, n), non_const_class(non_const_name, doc, n) { _register(); }
+public: // miscellaneous
 
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name, init_base<DerivedT> const & i) :
- const_class(const_name, i), non_const_class(non_const_name, i) { _register(); }
-
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name,
- char const * doc, init_base<DerivedT> const & i) :
- const_class(const_name, doc, i), non_const_class(non_const_name, doc, i) { _register(); }
+ self& enable_shared_ptr() {
+ register_ptr_to_python< boost::shared_ptr<wrapped> >();
+ const_aware::const_shared_ptr_to_python<wrapped>();
+ converter::shared_ptr_from_python<wrapped const>();
+ const_aware::shared_ptr_from_proxy<wrapped const>();
+ return *this;
+ }
 
 public: // member functions
 
@@ -149,8 +65,7 @@
     template <class Derived>
     self& def(def_visitor<Derived> const& visitor)
     {
- visitor.visit(non_const_class);
- visitor.visit(const_class);
+ visitor.visit(m_class);
         return *this;
     }
 
@@ -201,89 +116,63 @@
         return *this;
     }
 
-public:
+public: // data members
 
     template <typename D>
     self & def_readonly(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
+ m_class.def_readonly(name, d, doc);
+ m_proxy.use_property(name, m_class.attr(name));
         return *this;
     }
 
     template <typename D>
     self & def_readwrite(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
+ m_class.def_readwrite(name, d, doc);
+ m_proxy.use_property(name, m_class.attr(name));
         return *this;
     }
 
     template <typename D>
     self & def_readonly(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
+ m_class.def_readonly(name, d, doc);
+ m_proxy.use_property(name, m_class.attr(name));
         return *this;
     }
 
     template <typename D>
     self & def_readwrite(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
+ m_class.def_readwrite(name, d, doc);
+ m_proxy.use_property(name, m_class.attr(name));
         return *this;
     }
 
     template <class Get>
     self & add_property(char const* name, Get fget, char const* docstr = 0) {
- non_const_class.add_property(name, fget, docstr);
- const_class.add_property(name, fget, docstr);
+ m_class.add_property(name, fget, docstr);
+ m_proxy.use_property(name, m_class.attr(name));
         return *this;
     }
 
     template <class Get, class Set>
     self & add_property(char const* name, Get fget, Set fset, char const* docstr = 0) {
- non_const_class.add_property(name, fget, fset, docstr);
- const_class.add_property(name, fget, docstr);
+ m_class.add_property(name, fget, fset, docstr);
+ m_proxy.use_property(name, m_class.attr(name));
         return *this;
     }
-
- template <class Get>
- self & add_static_property(char const* name, Get fget) {
- non_const_class.add_static_property(name, fget);
- const_class.add_static_property(name, fget);
- return *this;
- }
-
- template <class Get, class Set>
- self & add_static_property(char const* name, Get fget, Set fset) {
- non_const_class.add_static_property(name, fget, fset);
- const_class.add_static_property(name, fget, fset);
- return *this;
- }
-
- template <class U>
- self & setattr(char const* name, U const& x) {
- non_const_class.setattr(name, x);
- const_class.setattr(name, x);
- return *this;
- }
-
+
     self & enable_pickling() {
- non_const_class.enable_pickling();
- const_class.enable_pickling();
+ m_class.enable_pickling();
         return *this;
     }
 
     self & staticmethod(char const* name) {
- non_const_class.staticmethod(name);
- const_class.static_method(name);
+ m_class.staticmethod(name);
+ m_proxy.setattr(name, m_class.attr(name));
         return *this;
     }
 
 private:
 
- void _register() {
- const_aware_registry::insert(non_const_class, const_class);
- }
-
     //
     // These two overloads discriminate between def() as applied to a
     // generic visitor and everything else.
@@ -298,8 +187,7 @@
       , def_visitor<Visitor> const* v
     )
     {
- v->visit(non_const_class, name, helper);
- v->visit(const_class, name, helper);
+ v->visit(m_class, name, helper);
     }
 
     template <class T, class Fn, class Helper>
@@ -318,10 +206,10 @@
                 , helper.keywords()
                 , detail::get_signature(fn, (T*)0)
             );
- objects::add_to_namespace(non_const_class, name, method, helper.doc());
+ objects::add_to_namespace(m_class, name, method, helper.doc());
 
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, method, helper.doc());
+ if (is_const_method<Fn>::value) {
+ m_proxy.use_method(name, method);
         }
 
     }
@@ -346,10 +234,10 @@
             helper.default_implementation(), helper.policies(), helper.keywords()
         );
 
- objects::add_to_namespace(non_const_class, name, default_method);
+ objects::add_to_namespace(m_class, name, default_method);
 
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, default_method);
+ if (is_const_method<Fn>::value) {
+ m_proxy.use_method(name, default_method);
         }
 
     }
@@ -394,10 +282,9 @@
 
     }
     // }
-};
 
-} // namespace boost::python
-} // namespace boost
+};
 
+}}} // namespace boost::python::const_aware
 
-#endif // !BOOST_PYTHON_CONST_AWARE_CLASS_HPP
+#endif // !BOOST_PYTHON_CONST_AWARE_EXPOSER_HPP

Added: sandbox/python_extensions/boost/python/const_aware/proxy_class.hpp
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/boost/python/const_aware/proxy_class.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,99 @@
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_PROXY_CLASS_HPP
+#define BOOST_PYTHON_CONST_AWARE_PROXY_CLASS_HPP
+
+#include <boost/python.hpp>
+#include <boost/python/const_aware/proxy_method.hpp>
+#include <boost/python/const_aware/rvalue_from_proxy.hpp>
+
+namespace boost { namespace python { namespace const_aware {
+
+// Mostly copied from objects::class_base in main Boost.Python library.
+struct proxy_class_base : python::api::object {
+
+ // constructor
+ proxy_class_base(
+ char const* name, // The name of the class
+
+ std::size_t num_types, // A list of class_ids. The first is the type
+ type_info const * const types, // this is wrapping. The rest are the types of
+ // any bases.
+
+ char const * doc = 0 // Docstring, if any.
+ );
+
+
+ // Implementation detail. Hiding this in the private section would
+ // require use of template friend declarations.
+ void enable_pickling_(bool getstate_manages_dict);
+
+protected:
+
+ // Retrieve the underlying object
+ void setattr(char const* name, object const&);
+
+};
+
+class proxy_class : proxy_class_base {
+
+ template <typename W, typename X1, typename X2, typename X3>
+ struct target_metadata {
+ typedef typename objects::class_metadata<W,X1,X2,X2> metadata;
+ typedef typename metadata::bases bases;
+ typedef typename metadata::wrapped wrapped;
+
+ target_metadata() {
+ // Stick the derived class id into the first element of the array
+ ids[0] = detail::unwrap_type_id((W*)0, (W*)0);
+
+ // Write the rest of the elements into succeeding positions.
+ type_info* p = ids + 1;
+ mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0);
+ }
+
+ BOOST_STATIC_CONSTANT(
+ std::size_t, size = mpl::size<bases>::value + 1);
+ type_info ids[size];
+
+ };
+
+public:
+
+ template <typename W, typename X1, typename X2, typename X3>
+ proxy_class(char const * name, class_<W,X1,X2,X3> & target, char const* doc=0)
+ : proxy_class_base(
+ name,
+ target_metadata<W,X1,X2,X3>::size,
+ target_metadata<W,X1,X2,X3>().ids,
+ doc
+ )
+ {
+ rvalue_from_proxy<typename target_metadata<W,X1,X2,X3>::wrapped>();
+ }
+
+public:
+
+ proxy_class & setattr(char const * name, object const & obj) {
+ proxy_class_base::setattr(name, obj);
+ return *this;
+ }
+
+ proxy_class & use_method(char const * name, object const & func) {
+ proxy_class_base::setattr(name, make_proxy_method(func));
+ return *this;
+ }
+
+ proxy_class & use_property(char const * name, object const & prop) {
+ proxy_class_base::setattr(name, make_proxy_property(prop));
+ return *this;
+ }
+
+};
+
+}}} // namespace boost::python::const_aware
+
+#endif // !BOOST_PYTHON_CONST_AWARE_PROXY_CLASS_HPP

Added: sandbox/python_extensions/boost/python/const_aware/proxy_class_fwd.hpp
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/boost/python/const_aware/proxy_class_fwd.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,25 @@
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_PROXY_CLASS_FWD_HPP
+#define BOOST_PYTHON_CONST_AWARE_PROXY_CLASS_FWD_HPP
+
+#include <boost/python.hpp>
+
+namespace boost { namespace python { namespace const_aware {
+
+// Construct a proxy class for a registered target (steals reference to target).
+PyObject * construct_proxy_class(PyObject * target);
+
+// Extract the target of a proxy class (returns a borrowed reference).
+// Returns 0 on error, but does not set a Python exception.
+PyObject * extract_proxy_target(PyObject * proxy);
+
+struct proxy_class_base;
+class proxy_class;
+
+}}} // namespace boost::python::const_aware
+
+#endif // !BOOST_PYTHON_CONST_AWARE_PROXY_CLASS_FWD_HPP

Added: sandbox/python_extensions/boost/python/const_aware/proxy_method.hpp
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/boost/python/const_aware/proxy_method.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,22 @@
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_PROXY_METHOD_HPP
+#define BOOST_PYTHON_CONST_AWARE_PROXY_METHOD_HPP
+
+#include <boost/python.hpp>
+
+namespace boost { namespace python { namespace const_aware {
+
+// Construct a proxy method that calls a regular method on a proxy class.
+object make_proxy_method(object const & target);
+
+// Construct a property object by replacing the given property's fget with
+// a proxy method and removing fset.
+object make_proxy_property(object const & target);
+
+}}} // namespace boost::python::const_aware
+
+#endif // !BOOST_PYTHON_CONST_AWARE_PROXY_METHOD_HPP

Copied: sandbox/python_extensions/boost/python/const_aware/registry.hpp (from r62162, /sandbox/python_extensions/boost/python/const_aware_class.hpp)
==============================================================================
--- /sandbox/python_extensions/boost/python/const_aware_class.hpp (original)
+++ sandbox/python_extensions/boost/python/const_aware/registry.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,403 +1,19 @@
-#ifndef BOOST_PYTHON_CONST_AWARE_CLASS_HPP
-#define BOOST_PYTHON_CONST_AWARE_CLASS_HPP
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
 
-#include <boost/python.hpp>
-#include <boost/function_types/parameter_types.hpp>
-#include <boost/mpl/front.hpp>
-#include <boost/type_traits/is_const.hpp>
-#include <boost/type_traits/remove_reference.hpp>
-#include <boost/static_assert.hpp>
-
-namespace boost {
-namespace python {
-
-namespace const_aware_registry {
-
-BOOST_PYTHON_DECL PyTypeObject * lookup(PyTypeObject * non_const);
-
-BOOST_PYTHON_DECL void insert(object const & non_const, object const & const_);
-
-} // namespace boost::python::const_aware_registry
-
-namespace objects {
-
-template <typename T, typename Holder>
-struct make_const_ptr_instance
- : make_instance_impl<T, Holder, make_const_ptr_instance<T,Holder> >
-{
-
- template <typename Arg>
- static inline Holder* construct(void* storage, PyObject*, Arg& x) {
- return new (storage) Holder(x);
- }
-
- template <typename Ptr>
- static inline PyTypeObject* get_class_object(Ptr const& x) {
- PyTypeObject * non_const = make_ptr_instance<T,Holder>::get_class_object(x);
- return const_aware_registry::lookup(non_const);
- }
-
-#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
- static inline PyTypeObject const* get_pytype()
- {
- return converter::registered<T>::converters.get_class_object();
- }
-#endif
-};
-
-} // namespace boost::python::objects
-
-namespace detail {
-
-template <typename F>
-struct is_const_method : public
-boost::is_const<
- typename boost::remove_reference<
- typename boost::mpl::front<
- boost::function_types::parameter_types<F>
- >::type
- >::type
- >
-{};
-
-struct make_const_reference_holder {
-
- template <typename T>
- static PyObject * execute(T* p) {
- typedef objects::pointer_holder<T*,T> holder_t;
- T* q = const_cast<T*>(p);
- return objects::make_const_ptr_instance<T, holder_t>::execute(q);
- }
-
-};
-
-} // namespace boost::python::detail
-
-struct const_reference_existing_object {
-
- template <class T>
- struct apply
- {
- BOOST_STATIC_CONSTANT(
- bool, ok = is_pointer<T>::value || is_reference<T>::value);
-
- typedef typename mpl::if_c<
- ok
- , to_python_indirect<T, detail::make_const_reference_holder>
- , detail::reference_existing_object_requires_a_pointer_or_reference_return_type<T>
- >::type type;
- };
-
-};
-
-template <std::size_t owner_arg = 1, class BasePolicy_ = default_call_policies>
-struct return_internal_const_reference
- : with_custodian_and_ward_postcall<0, owner_arg, BasePolicy_>
-{
- private:
- BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0);
- public:
- typedef typename mpl::if_c<
- legal
- , const_reference_existing_object
- , detail::return_internal_reference_owner_arg_must_be_greater_than_zero<owner_arg>
- >::type result_converter;
-};
-
-template <
- typename W,
- typename X1 = detail::not_specified,
- typename X2 = detail::not_specified,
- typename X3 = detail::not_specified
- >
-class const_aware_class {
-public:
-
- typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
- typedef const_aware_class<W,X1,X2,X3> self;
-
- typedef class_<W,X1,X2,X3> const_class_t;
- typedef class_< W, typename metadata::held_type_arg, typename metadata::bases, boost::noncopyable
- > non_const_class_t;
-
- const_class_t const_class;
- non_const_class_t non_const_class;
-
-public: // constructors
-
- const_aware_class(char const * non_const_name, char const * const_name, char const* doc = 0) :
- const_class(const_name, doc), non_const_class(non_const_name, doc) { _register(); }
-
- const_aware_class(char const * non_const_name, char const * const_name, no_init_t n) :
- const_class(const_name, n), non_const_class(non_const_name, n) { _register(); }
-
- const_aware_class(char const * non_const_name, char const * const_name, char const * doc, no_init_t n) :
- const_class(const_name, doc, n), non_const_class(non_const_name, doc, n) { _register(); }
-
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name, init_base<DerivedT> const & i) :
- const_class(const_name, i), non_const_class(non_const_name, i) { _register(); }
-
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name,
- char const * doc, init_base<DerivedT> const & i) :
- const_class(const_name, doc, i), non_const_class(non_const_name, doc, i) { _register(); }
-
-public: // member functions
+#ifndef BOOST_PYTHON_CONST_AWARE_REGISTRY_HPP
+#define BOOST_PYTHON_CONST_AWARE_REGISTRY_HPP
 
- // Generic visitation
- template <class Derived>
- self& def(def_visitor<Derived> const& visitor)
- {
- visitor.visit(non_const_class);
- visitor.visit(const_class);
- return *this;
- }
-
- // Wrap a member function or a non-member function which can take
- // a T, T cv&, or T cv* as its first parameter, a callable
- // python object, or a generic visitor.
- template <class F>
- self& def(char const* name, F f)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, f, detail::def_helper<char const*>(0), &f);
- return *this;
- }
-
- template <class A1, class A2>
- self& def(char const* name, A1 a1, A2 const& a2)
- {
- this->def_maybe_overloads(name, a1, a2, &a2);
- return *this;
- }
-
- template <class Fn, class A1, class A2>
- self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
- {
- // The arguments are definitely:
- // def(name, function, policy, doc_string)
- // def(name, function, doc_string, policy)
-
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, fn
- , detail::def_helper<A1,A2>(a1,a2)
- , &fn);
-
- return *this;
- }
-
- template <class Fn, class A1, class A2, class A3>
- self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, fn
- , detail::def_helper<A1,A2,A3>(a1,a2,a3)
- , &fn);
-
- return *this;
- }
-
-public:
-
- template <typename D>
- self & def_readonly(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readwrite(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readonly(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readwrite(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <class Get>
- self & add_property(char const* name, Get fget, char const* docstr = 0) {
- non_const_class.add_property(name, fget, docstr);
- const_class.add_property(name, fget, docstr);
- return *this;
- }
-
- template <class Get, class Set>
- self & add_property(char const* name, Get fget, Set fset, char const* docstr = 0) {
- non_const_class.add_property(name, fget, fset, docstr);
- const_class.add_property(name, fget, docstr);
- return *this;
- }
-
- template <class Get>
- self & add_static_property(char const* name, Get fget) {
- non_const_class.add_static_property(name, fget);
- const_class.add_static_property(name, fget);
- return *this;
- }
-
- template <class Get, class Set>
- self & add_static_property(char const* name, Get fget, Set fset) {
- non_const_class.add_static_property(name, fget, fset);
- const_class.add_static_property(name, fget, fset);
- return *this;
- }
-
- template <class U>
- self & setattr(char const* name, U const& x) {
- non_const_class.setattr(name, x);
- const_class.setattr(name, x);
- return *this;
- }
-
- self & enable_pickling() {
- non_const_class.enable_pickling();
- const_class.enable_pickling();
- return *this;
- }
-
- self & staticmethod(char const* name) {
- non_const_class.staticmethod(name);
- const_class.static_method(name);
- return *this;
- }
-
-private:
-
- void _register() {
- const_aware_registry::insert(non_const_class, const_class);
- }
-
- //
- // These two overloads discriminate between def() as applied to a
- // generic visitor and everything else.
- //
- // @group def_impl {
- template <class T, class Helper, class LeafVisitor, class Visitor>
- inline void def_impl(
- T*
- , char const* name
- , LeafVisitor
- , Helper const& helper
- , def_visitor<Visitor> const* v
- )
- {
- v->visit(non_const_class, name, helper);
- v->visit(const_class, name, helper);
- }
-
- template <class T, class Fn, class Helper>
- inline void def_impl(
- T*
- , char const* name
- , Fn fn
- , Helper const& helper
- , ...
- )
- {
- object method =
- make_function(
- fn
- , helper.policies()
- , helper.keywords()
- , detail::get_signature(fn, (T*)0)
- );
- objects::add_to_namespace(non_const_class, name, method, helper.doc());
-
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, method, helper.doc());
- }
-
- }
-
- //
- // These two overloads handle the definition of default
- // implementation overloads for virtual functions. The second one
- // handles the case where no default implementation was specified.
- //
- // @group def_default {
- template <class Fn, class Helper>
- inline void def_default(
- char const* name
- , Fn
- , Helper const& helper
- , mpl::bool_<true>)
- {
- detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
- helper.default_implementation());
-
- object default_method = make_function(
- helper.default_implementation(), helper.policies(), helper.keywords()
- );
-
- objects::add_to_namespace(non_const_class, name, default_method);
-
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, default_method);
- }
-
- }
-
- template <class Fn, class Helper>
- inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
- { }
- // }
-
- //
- // These two overloads discriminate between def() as applied to
- // regular functions and def() as applied to the result of
- // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
- // discriminate.
- //
- // @group def_maybe_overloads {
- template <class OverloadsT, class SigT>
- void def_maybe_overloads(
- char const* name
- , SigT sig
- , OverloadsT const& overloads
- , detail::overloads_base const*)
-
- {
- BOOST_STATIC_ASSERT(sizeof(SigT) < 0); // No support for overload macros (yet).
- }
+#include <boost/python.hpp>
 
- template <class Fn, class A1>
- void def_maybe_overloads(
- char const* name
- , Fn fn
- , A1 const& a1
- , ...)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name
- , fn
- , detail::def_helper<A1>(a1)
- , &fn
- );
+namespace boost { namespace python { namespace const_aware { namespace registry {
 
- }
- // }
-};
+BOOST_PYTHON_DECL PyTypeObject * query(PyTypeObject const * non_const);
 
-} // namespace boost::python
-} // namespace boost
+BOOST_PYTHON_DECL void insert(PyTypeObject * non_const, PyTypeObject * const_);
 
+}}}} // namespace boost::python::const_aware::registry
 
-#endif // !BOOST_PYTHON_CONST_AWARE_CLASS_HPP
+#endif // !BOOST_PYTHON_CONST_AWARE_REGISTRY_HPP

Added: sandbox/python_extensions/boost/python/const_aware/rvalue_from_proxy.hpp
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/boost/python/const_aware/rvalue_from_proxy.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,41 @@
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_RVALUE_FROM_PROXY_HPP
+#define BOOST_PYTHON_CONST_AWARE_RVALUE_FROM_PROXY_HPP
+
+#include <boost/python.hpp>
+#include <boost/python/object/find_instance.hpp>
+#include <boost/python/const_aware/proxy_class_fwd.hpp>
+
+namespace boost { namespace python { namespace const_aware {
+
+template <typename T>
+struct rvalue_from_proxy {
+
+ static void* convertible(PyObject * arg) {
+ PyObject * target = extract_proxy_target(arg);
+ if (target == 0) return 0;
+ converter::registration const & converters = converter::registered<T>::converters;
+ return objects::find_instance_impl(target, converters.target_type, converters.is_shared_ptr);
+ }
+
+ static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data) {
+ data->construct = 0;
+ }
+
+ rvalue_from_proxy() {
+ converter::registry::insert(
+ &convertible,
+ &construct,
+ type_id< T >()
+ );
+ }
+
+};
+
+}}} // namespace boost::python::const_aware
+
+#endif // !BOOST_PYTHON_CONST_AWARE_RVALUE_FROM_PROXY_HPP

Added: sandbox/python_extensions/boost/python/const_aware/shared_ptr_from_proxy.hpp
==============================================================================
--- (empty file)
+++ sandbox/python_extensions/boost/python/const_aware/shared_ptr_from_proxy.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -0,0 +1,60 @@
+// Copyright 2010 Jim Bosch.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PYTHON_CONST_AWARE_SHARED_PTR_FROM_PROXY_HPP
+#define BOOST_PYTHON_CONST_AWARE_SHARED_PTR_FROM_PROXY_HPP
+
+#include <boost/python.hpp>
+#include <boost/python/object/find_instance.hpp>
+#include <boost/python/const_aware/proxy_class_fwd.hpp>
+
+namespace boost { namespace python { namespace const_aware {
+
+template <typename T>
+struct shared_ptr_from_proxy {
+
+ shared_ptr_from_proxy()
+ {
+ converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >()
+#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
+ , &converter::expected_from_python_type_direct<T>::get_pytype
+#endif
+ );
+ }
+
+ private:
+ static void* convertible(PyObject* p)
+ {
+ if (p == Py_None)
+ return p;
+ PyObject * target = extract_proxy_target(p);
+ if (target == 0) return 0;
+ return converter::get_lvalue_from_python(target, converter::registered<T>::converters);
+ }
+
+ static void construct(PyObject* source, converter::rvalue_from_python_stage1_data* data)
+ {
+ void* const storage = ((converter::rvalue_from_python_storage<shared_ptr<T> >*)data)->storage.bytes;
+ // Deal with the "None" case.
+ if (data->convertible == Py_None)
+ new (storage) shared_ptr<T>();
+ else
+ {
+ boost::shared_ptr<void> hold_convertible_ref_count(
+ (void*)0, converter::shared_ptr_deleter(handle<>(borrowed(source))) );
+ // use aliasing constructor
+ new (storage) shared_ptr<T>(
+ hold_convertible_ref_count,
+ static_cast<T*>(data->convertible));
+ }
+
+ data->convertible = storage;
+ }
+
+};
+
+}}} // namespace boost::python::const_aware
+
+#endif // !BOOST_PYTHON_CONST_AWARE_SHARED_PTR_FROM_PROXY_HPP

Deleted: sandbox/python_extensions/boost/python/const_aware_class.hpp
==============================================================================
--- sandbox/python_extensions/boost/python/const_aware_class.hpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
+++ (empty file)
@@ -1,403 +0,0 @@
-#ifndef BOOST_PYTHON_CONST_AWARE_CLASS_HPP
-#define BOOST_PYTHON_CONST_AWARE_CLASS_HPP
-
-#include <boost/python.hpp>
-#include <boost/function_types/parameter_types.hpp>
-#include <boost/mpl/front.hpp>
-#include <boost/type_traits/is_const.hpp>
-#include <boost/type_traits/remove_reference.hpp>
-#include <boost/static_assert.hpp>
-
-namespace boost {
-namespace python {
-
-namespace const_aware_registry {
-
-BOOST_PYTHON_DECL PyTypeObject * lookup(PyTypeObject * non_const);
-
-BOOST_PYTHON_DECL void insert(object const & non_const, object const & const_);
-
-} // namespace boost::python::const_aware_registry
-
-namespace objects {
-
-template <typename T, typename Holder>
-struct make_const_ptr_instance
- : make_instance_impl<T, Holder, make_const_ptr_instance<T,Holder> >
-{
-
- template <typename Arg>
- static inline Holder* construct(void* storage, PyObject*, Arg& x) {
- return new (storage) Holder(x);
- }
-
- template <typename Ptr>
- static inline PyTypeObject* get_class_object(Ptr const& x) {
- PyTypeObject * non_const = make_ptr_instance<T,Holder>::get_class_object(x);
- return const_aware_registry::lookup(non_const);
- }
-
-#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
- static inline PyTypeObject const* get_pytype()
- {
- return converter::registered<T>::converters.get_class_object();
- }
-#endif
-};
-
-} // namespace boost::python::objects
-
-namespace detail {
-
-template <typename F>
-struct is_const_method : public
-boost::is_const<
- typename boost::remove_reference<
- typename boost::mpl::front<
- boost::function_types::parameter_types<F>
- >::type
- >::type
- >
-{};
-
-struct make_const_reference_holder {
-
- template <typename T>
- static PyObject * execute(T* p) {
- typedef objects::pointer_holder<T*,T> holder_t;
- T* q = const_cast<T*>(p);
- return objects::make_const_ptr_instance<T, holder_t>::execute(q);
- }
-
-};
-
-} // namespace boost::python::detail
-
-struct const_reference_existing_object {
-
- template <class T>
- struct apply
- {
- BOOST_STATIC_CONSTANT(
- bool, ok = is_pointer<T>::value || is_reference<T>::value);
-
- typedef typename mpl::if_c<
- ok
- , to_python_indirect<T, detail::make_const_reference_holder>
- , detail::reference_existing_object_requires_a_pointer_or_reference_return_type<T>
- >::type type;
- };
-
-};
-
-template <std::size_t owner_arg = 1, class BasePolicy_ = default_call_policies>
-struct return_internal_const_reference
- : with_custodian_and_ward_postcall<0, owner_arg, BasePolicy_>
-{
- private:
- BOOST_STATIC_CONSTANT(bool, legal = owner_arg > 0);
- public:
- typedef typename mpl::if_c<
- legal
- , const_reference_existing_object
- , detail::return_internal_reference_owner_arg_must_be_greater_than_zero<owner_arg>
- >::type result_converter;
-};
-
-template <
- typename W,
- typename X1 = detail::not_specified,
- typename X2 = detail::not_specified,
- typename X3 = detail::not_specified
- >
-class const_aware_class {
-public:
-
- typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
- typedef const_aware_class<W,X1,X2,X3> self;
-
- typedef class_<W,X1,X2,X3> const_class_t;
- typedef class_< W, typename metadata::held_type_arg, typename metadata::bases, boost::noncopyable
- > non_const_class_t;
-
- const_class_t const_class;
- non_const_class_t non_const_class;
-
-public: // constructors
-
- const_aware_class(char const * non_const_name, char const * const_name, char const* doc = 0) :
- const_class(const_name, doc), non_const_class(non_const_name, doc) { _register(); }
-
- const_aware_class(char const * non_const_name, char const * const_name, no_init_t n) :
- const_class(const_name, n), non_const_class(non_const_name, n) { _register(); }
-
- const_aware_class(char const * non_const_name, char const * const_name, char const * doc, no_init_t n) :
- const_class(const_name, doc, n), non_const_class(non_const_name, doc, n) { _register(); }
-
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name, init_base<DerivedT> const & i) :
- const_class(const_name, i), non_const_class(non_const_name, i) { _register(); }
-
- template <typename DerivedT>
- const_aware_class(char const * non_const_name, char const * const_name,
- char const * doc, init_base<DerivedT> const & i) :
- const_class(const_name, doc, i), non_const_class(non_const_name, doc, i) { _register(); }
-
-public: // member functions
-
- // Generic visitation
- template <class Derived>
- self& def(def_visitor<Derived> const& visitor)
- {
- visitor.visit(non_const_class);
- visitor.visit(const_class);
- return *this;
- }
-
- // Wrap a member function or a non-member function which can take
- // a T, T cv&, or T cv* as its first parameter, a callable
- // python object, or a generic visitor.
- template <class F>
- self& def(char const* name, F f)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, f, detail::def_helper<char const*>(0), &f);
- return *this;
- }
-
- template <class A1, class A2>
- self& def(char const* name, A1 a1, A2 const& a2)
- {
- this->def_maybe_overloads(name, a1, a2, &a2);
- return *this;
- }
-
- template <class Fn, class A1, class A2>
- self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
- {
- // The arguments are definitely:
- // def(name, function, policy, doc_string)
- // def(name, function, doc_string, policy)
-
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, fn
- , detail::def_helper<A1,A2>(a1,a2)
- , &fn);
-
- return *this;
- }
-
- template <class Fn, class A1, class A2, class A3>
- self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name, fn
- , detail::def_helper<A1,A2,A3>(a1,a2,a3)
- , &fn);
-
- return *this;
- }
-
-public:
-
- template <typename D>
- self & def_readonly(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readwrite(char const* name, D const & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readonly(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readonly(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <typename D>
- self & def_readwrite(char const* name, D & d, char const* doc=0) {
- non_const_class.def_readwrite(name, d, doc);
- const_class.def_readonly(name, d, doc);
- return *this;
- }
-
- template <class Get>
- self & add_property(char const* name, Get fget, char const* docstr = 0) {
- non_const_class.add_property(name, fget, docstr);
- const_class.add_property(name, fget, docstr);
- return *this;
- }
-
- template <class Get, class Set>
- self & add_property(char const* name, Get fget, Set fset, char const* docstr = 0) {
- non_const_class.add_property(name, fget, fset, docstr);
- const_class.add_property(name, fget, docstr);
- return *this;
- }
-
- template <class Get>
- self & add_static_property(char const* name, Get fget) {
- non_const_class.add_static_property(name, fget);
- const_class.add_static_property(name, fget);
- return *this;
- }
-
- template <class Get, class Set>
- self & add_static_property(char const* name, Get fget, Set fset) {
- non_const_class.add_static_property(name, fget, fset);
- const_class.add_static_property(name, fget, fset);
- return *this;
- }
-
- template <class U>
- self & setattr(char const* name, U const& x) {
- non_const_class.setattr(name, x);
- const_class.setattr(name, x);
- return *this;
- }
-
- self & enable_pickling() {
- non_const_class.enable_pickling();
- const_class.enable_pickling();
- return *this;
- }
-
- self & staticmethod(char const* name) {
- non_const_class.staticmethod(name);
- const_class.static_method(name);
- return *this;
- }
-
-private:
-
- void _register() {
- const_aware_registry::insert(non_const_class, const_class);
- }
-
- //
- // These two overloads discriminate between def() as applied to a
- // generic visitor and everything else.
- //
- // @group def_impl {
- template <class T, class Helper, class LeafVisitor, class Visitor>
- inline void def_impl(
- T*
- , char const* name
- , LeafVisitor
- , Helper const& helper
- , def_visitor<Visitor> const* v
- )
- {
- v->visit(non_const_class, name, helper);
- v->visit(const_class, name, helper);
- }
-
- template <class T, class Fn, class Helper>
- inline void def_impl(
- T*
- , char const* name
- , Fn fn
- , Helper const& helper
- , ...
- )
- {
- object method =
- make_function(
- fn
- , helper.policies()
- , helper.keywords()
- , detail::get_signature(fn, (T*)0)
- );
- objects::add_to_namespace(non_const_class, name, method, helper.doc());
-
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, method, helper.doc());
- }
-
- }
-
- //
- // These two overloads handle the definition of default
- // implementation overloads for virtual functions. The second one
- // handles the case where no default implementation was specified.
- //
- // @group def_default {
- template <class Fn, class Helper>
- inline void def_default(
- char const* name
- , Fn
- , Helper const& helper
- , mpl::bool_<true>)
- {
- detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
- helper.default_implementation());
-
- object default_method = make_function(
- helper.default_implementation(), helper.policies(), helper.keywords()
- );
-
- objects::add_to_namespace(non_const_class, name, default_method);
-
- if (detail::is_const_method<Fn>::value) {
- objects::add_to_namespace(const_class, name, default_method);
- }
-
- }
-
- template <class Fn, class Helper>
- inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
- { }
- // }
-
- //
- // These two overloads discriminate between def() as applied to
- // regular functions and def() as applied to the result of
- // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
- // discriminate.
- //
- // @group def_maybe_overloads {
- template <class OverloadsT, class SigT>
- void def_maybe_overloads(
- char const* name
- , SigT sig
- , OverloadsT const& overloads
- , detail::overloads_base const*)
-
- {
- BOOST_STATIC_ASSERT(sizeof(SigT) < 0); // No support for overload macros (yet).
- }
-
- template <class Fn, class A1>
- void def_maybe_overloads(
- char const* name
- , Fn fn
- , A1 const& a1
- , ...)
- {
- this->def_impl(
- detail::unwrap_wrapper((W*)0)
- , name
- , fn
- , detail::def_helper<A1>(a1)
- , &fn
- );
-
- }
- // }
-};
-
-} // namespace boost::python
-} // namespace boost
-
-
-#endif // !BOOST_PYTHON_CONST_AWARE_CLASS_HPP

Copied: sandbox/python_extensions/libs/python/src/SConscript (from r62136, /sandbox/numpy/libs/python/numpy/src/SConscript)
==============================================================================
--- /sandbox/numpy/libs/python/numpy/src/SConscript (original)
+++ sandbox/python_extensions/libs/python/src/SConscript 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,5 +1,5 @@
-Import("bp_numpy_env")
+Import("bp_extensions_env")
 
-lib = bp_numpy_env.SharedLibrary("boost_python_numpy", Glob("*.cpp"))
+lib = bp_extensions_env.SharedLibrary("boost_python_extensions", Glob("*.cpp"))
 
 Return("lib")

Copied: sandbox/python_extensions/libs/python/src/proxy_class.cpp (from r62162, /sandbox/python_extensions/libs/python/test/const_aware.cpp)
==============================================================================
--- /sandbox/python_extensions/libs/python/test/const_aware.cpp (original)
+++ sandbox/python_extensions/libs/python/src/proxy_class.cpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,71 +1,358 @@
+// Copyright 2010 Jim Bosch
+// Adapted from Boost.Python code, Copyright David Abrahams, 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
 #include <boost/python.hpp>
-#include <boost/python/const_aware_class.hpp>
+#include <boost/python/const_aware/proxy_class.hpp>
+#include <boost/python/const_aware/registry.hpp>
+#include <structmember.h>
+
+// Most of this is copied with minor modifications from object/class.cpp in the main Boost.Python library.
+
+namespace boost { namespace python { namespace const_aware {
+
+struct proxy_instance {
+ PyObject_HEAD
+ PyObject* dict;
+ PyObject* weakrefs;
+ PyObject* target;
+};
 
-#include <iostream>
-#include <map>
+extern "C" {
+
+ static int
+ type_is_gc(PyTypeObject *python_type) {
+ return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
+ }
+
+ static void proxy_instance_dealloc(PyObject* inst) {
+ proxy_instance* kill_me = (proxy_instance*)inst;
+
+ Py_DECREF(kill_me->target);
+
+ // 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);
+
+ Py_TYPE(inst)->tp_free(inst);
+ }
+
+ static PyObject *
+ proxy_instance_new(PyTypeObject* type_, PyObject* /*args*/, PyObject* /*kw*/) {
+ proxy_instance* result = (proxy_instance*)type_->tp_alloc(type_, 0);
+ return (PyObject*)result;
+ }
+
+ static PyObject* proxy_instance_get_dict(PyObject* op, void*) {
+ proxy_instance* inst = downcast<proxy_instance>(op);
+ if (inst->dict == 0)
+ inst->dict = PyDict_New();
+ return python::xincref(inst->dict);
+ }
+
+ static int proxy_instance_set_dict(PyObject* op, PyObject* dict, void*) {
+ proxy_instance* inst = downcast<proxy_instance>(op);
+ python::xdecref(inst->dict);
+ inst->dict = python::incref(dict);
+ return 0;
+ }
+
+} // extern "C"
+
+// Mostly copied from class_metatype_object from object/class.cpp in the main Boost.Python library.
+static PyTypeObject proxy_class_metatype_object = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ const_cast<char*>("Boost.Python.proxy_class"),
+ PyType_Type.tp_basicsize,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
+ | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, //&PyType_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, // filled in with type_new /* tp_new */
+ 0, // filled in with __PyObject_GC_Del /* tp_free */
+ (inquiry)type_is_gc, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#if PYTHON_API_VERSION >= 1012
+ 0 /* tp_del */
+#endif
+};
 
-namespace bp = boost::python;
+static PyGetSetDef proxy_instance_getsets[] = {
+ {const_cast<char*>("__dict__"), proxy_instance_get_dict, proxy_instance_set_dict, NULL, 0},
+ {0, 0, 0, 0, 0}
+};
 
-namespace boost { namespace python { namespace const_aware_registry {
+
+static PyMemberDef proxy_instance_members[] = {
+ {const_cast<char*>("__weakref__"), T_OBJECT, offsetof(proxy_instance, weakrefs), 0, 0},
+ {0, 0, 0, 0, 0}
+};
 
-namespace {
-typedef std::map<PyTypeObject*,PyTypeObject*> registry_t;
-registry_t registry;
+static PyTypeObject proxy_class_type_object = {
+ PyVarObject_HEAD_INIT(NULL,0)
+ const_cast<char*>("Boost.Python.proxy_instance"),
+ sizeof(proxy_instance), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ proxy_instance_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
+ | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(proxy_instance,weakrefs), /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ proxy_instance_members, /* tp_members */
+ proxy_instance_getsets, /* tp_getset */
+ 0, //&PyBaseObject_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(proxy_instance,dict), /* tp_dictoffset */
+ 0, /* tp_init */
+ PyType_GenericAlloc, /* tp_alloc */
+ proxy_instance_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#if PYTHON_API_VERSION >= 1012
+ 0 /* tp_del */
+#endif
+ };
+
+type_handle proxy_class_metatype() {
+ if (proxy_class_metatype_object.tp_dict == 0) {
+ Py_TYPE(&proxy_class_metatype_object) = &PyType_Type;
+ proxy_class_metatype_object.tp_base = &PyType_Type;
+ if (PyType_Ready(&proxy_class_metatype_object))
+ return type_handle();
+ }
+ return type_handle(borrowed(&proxy_class_metatype_object));
 }
 
-PyTypeObject * lookup(PyTypeObject* non_const) {
- registry_t::const_iterator iter = registry.find(non_const);
- if (iter != registry.end()) return iter->second;
- return NULL;
+type_handle proxy_class_type() {
+ if (proxy_class_type_object.tp_dict == 0) {
+ Py_TYPE(&proxy_class_type_object) = incref(proxy_class_metatype().get());
+ proxy_class_type_object.tp_base = &PyBaseObject_Type;
+ if (PyType_Ready(&proxy_class_type_object))
+ return type_handle();
+ }
+ return type_handle(borrowed(&proxy_class_type_object));
 }
 
-void insert(object const & non_const, object const & const_) {
- registry.insert(
- registry_t::value_type(
- reinterpret_cast<PyTypeObject*>(non_const.ptr()),
- reinterpret_cast<PyTypeObject*>(const_.ptr())
- )
+namespace { // <unnamed>
+
+object module_prefix() {
+ return object(
+ PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
+ ? object(scope().attr("__name__"))
+ : api::getattr(scope(), "__module__", str())
     );
 }
 
-}}}
+// Find a registered extension class object corresponding to id. Return a
+// null handle if no such class is registered.
+inline type_handle query_target_class(type_info id) {
+ converter::registration const* p = converter::registry::query(id);
+ return type_handle(
+ python::borrowed(
+ python::allow_null(p ? p->m_class_object : 0))
+ );
+}
 
-class Example {
-public:
- std::size_t get_address() const { return std::size_t(this); }
+// Find a registered extension corresponding to id. If not found,
+// throw an appropriate exception.
+type_handle get_target_class(type_info id) {
+ type_handle result(query_target_class(id));
+
+ if (result.get() == 0)
+ {
+ object report("extension class wrapper for proxy target class ");
+ report = report + id.name() + " has not been created yet";
+ PyErr_SetObject(PyExc_RuntimeError, report.ptr());
+ throw_error_already_set();
+ }
+ return result;
+}
 
- bool non_const_method() { return true; }
+// Find a registered proxy class object corresponding to id. Return a
+// null handle if no such class is registered.
+inline type_handle query_proxy_class(type_info id) {
+ converter::registration const* p = converter::registry::query(id);
+ return type_handle(
+ python::borrowed(
+ python::allow_null(p ? const_aware::registry::query(p->m_class_object) : 0))
+ );
+}
 
- bool const_method() const { return true; }
-};
+// Find a registered proxy class corresponding to id. If not found,
+// throw an appropriate exception.
+type_handle get_proxy_class(type_info id) {
+ type_handle result(query_proxy_class(id));
+
+ if (result.get() == 0)
+ {
+ object report("proxy class wrapper for base class ");
+ report = report + id.name() + " has not been created yet";
+ PyErr_SetObject(PyExc_RuntimeError, report.ptr());
+ throw_error_already_set();
+ }
+ return result;
+}
 
-class Owner {
-public:
- Example by_value() const { return _example; }
- Example const by_const_value() const { return _example; }
- Example & by_reference() { return _example; }
- Example const & by_const_reference() const { return _example; }
-private:
- Example _example;
-};
+// proxy_class_base constructor
+//
+// name - the name of the new Python class
+//
+// num_types - one more than the number of declared bases
+//
+// types - array of python::type_info, the first item
+// corresponding to the class being created, and the
+// rest corresponding to its declared bases.
+//
+inline object
+new_proxy_class(char const* name, std::size_t num_types, type_info const* const types, char const* doc) {
+ assert(num_types >= 1);
+
+ // Build a tuple of the base Python type objects. If no bases
+ // were declared, we'll use our class_type() as the single base
+ // class.
+ ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
+ handle<> bases(PyTuple_New(num_bases));
+
+ for (ssize_t i = 1; i <= num_bases; ++i) {
+ type_handle c = (i >= static_cast<ssize_t>(num_types))
+ ? proxy_class_type() : get_proxy_class(types[i]);
+ // PyTuple_SET_ITEM steals this reference
+ PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
+ }
+
+ // Call the class metatype to create a new class
+ dict d;
+
+ object m = module_prefix();
+ if (m) d["__module__"] = m;
+
+ if (doc != 0)
+ d["__doc__"] = doc;
+
+ type_handle target = get_target_class(types[0]);
+ d["__proxy_target__"] = object(target);
 
-static void export_module() {
+ object result = object(proxy_class_metatype())(name, bases, d);
+ assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type));
     
- bp::const_aware_class<Example>("Example", "FrozenExample")
- .add_property("address", &Example::get_address)
- .def("non_const_method", &Example::non_const_method)
- .def("const_method", &Example::const_method)
- ;
+ if (scope().ptr() != Py_None)
+ scope().attr(name) = result;
+
+ return result;
+}
 
- bp::class_<Owner>("Owner")
- .def("by_value", &Owner::by_value)
- .def("by_const_value", &Owner::by_const_value)
- .def("by_reference", &Owner::by_reference, bp::return_internal_reference<>())
- .def("by_const_reference", &Owner::by_const_reference, bp::return_internal_const_reference<>())
- ;
+} // <unnamed>
+
+proxy_class_base::proxy_class_base(
+ char const* name, std::size_t num_types, type_info const* const types, char const* doc)
+ : object(new_proxy_class(name, num_types, types, doc))
+{
+ // Insert the new class object in the const_registry
+ // Class object is leaked, for now
+ object target = this->attr("__proxy_target__");
+ const_aware::registry::insert(
+ (PyTypeObject*)target.ptr(),
+ (PyTypeObject*)incref(this->ptr())
+ );
+}
 
+void proxy_class_base::setattr(char const* name, object const& x) {
+ if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.ptr()) < 0)
+ throw_error_already_set();
 }
 
-BOOST_PYTHON_MODULE(const_aware) {
- export_module();
+PyObject * construct_proxy_class(PyObject * target_arg) {
+ handle<> target(target_arg);
+ PyTypeObject * target_type = Py_TYPE(target.get());
+ PyTypeObject * proxy_type = const_aware::registry::query(target_type);
+ if (proxy_type == 0) {
+ object report("no const proxy class registered for objects of type ");
+ report = report + str(object(type_handle(borrowed(target_type))));
+ PyErr_SetObject(PyExc_RuntimeError, report.ptr());
+ throw_error_already_set();
+ }
+ PyObject * raw_proxy = proxy_type->tp_alloc(proxy_type, 0);
+ if (raw_proxy != 0) {
+ proxy_instance * proxy = (proxy_instance*)raw_proxy;
+ proxy->target = target.release();
+ }
+ return raw_proxy;
 }
+
+PyObject * extract_proxy_target(PyObject * proxy) {
+ if (Py_TYPE(Py_TYPE(proxy)) != &proxy_class_metatype_object)
+ return 0;
+ proxy_instance* self = reinterpret_cast<proxy_instance*>(proxy);
+ return self->target;
+}
+
+}}} // namespace boost::python::const_aware

Copied: sandbox/python_extensions/libs/python/src/proxy_method.cpp (from r62162, /sandbox/python_extensions/libs/python/test/const_aware.cpp)
==============================================================================
--- /sandbox/python_extensions/libs/python/test/const_aware.cpp (original)
+++ sandbox/python_extensions/libs/python/src/proxy_method.cpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,71 +1,199 @@
-#include <boost/python.hpp>
-#include <boost/python/const_aware_class.hpp>
-
-#include <iostream>
-#include <map>
+// Copyright 2010 Jim Bosch
+// Adapted from Boost.Python code, Copyright David Abrahams, 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
 
-namespace bp = boost::python;
+#include <boost/python.hpp>
+#include <boost/python/const_aware/proxy_class.hpp>
+#include <boost/python/const_aware/proxy_method.hpp>
+#include <structmember.h>
 
-namespace boost { namespace python { namespace const_aware_registry {
+// Most of this is copied with minor modifications from object/function.cpp in the main Boost.Python library.
 
-namespace {
-typedef std::map<PyTypeObject*,PyTypeObject*> registry_t;
-registry_t registry;
-}
+namespace boost { namespace python { namespace const_aware {
 
-PyTypeObject * lookup(PyTypeObject* non_const) {
- registry_t::const_iterator iter = registry.find(non_const);
- if (iter != registry.end()) return iter->second;
- return NULL;
-}
+struct proxy_method {
+ PyObject_HEAD
+ PyObject* target;
+};
 
-void insert(object const & non_const, object const & const_) {
- registry.insert(
- registry_t::value_type(
- reinterpret_cast<PyTypeObject*>(non_const.ptr()),
- reinterpret_cast<PyTypeObject*>(const_.ptr())
- )
- );
+extern "C"
+{
+ // Stolen from Python's funcobject.c
+ static PyObject *
+ proxy_method_descr_get(PyObject *func, PyObject *obj, PyObject *type_)
+ {
+#if PY_VERSION_HEX >= 0x03000000
+ // The implement is different in Python 3 because of the removal of unbound method
+ if (obj == Py_None || obj == NULL) {
+ Py_INCREF(func);
+ return func;
+ }
+ return PyMethod_New(func, obj);
+#else
+ if (obj == Py_None)
+ obj = NULL;
+ return PyMethod_New(func, obj, type_);
+#endif
+ }
+
+ static void
+ proxy_method_dealloc(PyObject* p) {
+ proxy_method* self = (proxy_method*)p;
+ Py_DECREF(self->target);
+ Py_TYPE(p)->tp_free(p);
+ }
+
+ static PyObject *
+ proxy_method_call(PyObject *func, PyObject *args, PyObject *kw) {
+ proxy_method* self = downcast<proxy_method>(func);
+ Py_ssize_t n_args = PyTuple_GET_SIZE(args);
+ if (n_args < 1) {
+ PyErr_SetString(PyExc_ValueError, "proxy_method.__call__ requires at least one argument");
+ return 0;
+ }
+ PyObject * proxy_arg = PyTuple_GET_ITEM(args,0);
+ PyObject * target_arg = extract_proxy_target(proxy_arg);
+ if (target_arg == 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "proxy_method.__call__ requires the first argument to be a proxy_instance");
+ return 0;
+ }
+ PyObject * new_args = PyTuple_New(n_args);
+ Py_INCREF(target_arg);
+ PyTuple_SET_ITEM(new_args, 0, target_arg);
+ for (Py_ssize_t n = 1; n < n_args; ++n) {
+ PyObject * arg_n = PyTuple_GET_ITEM(args, n);
+ Py_INCREF(arg_n);
+ PyTuple_SET_ITEM(new_args, n, arg_n);
+ }
+ PyObject * result = PyObject_Call(self->target, new_args, kw);
+ Py_DECREF(new_args);
+ return result;
+ }
+
+ //
+ // Here we're using the function's tp_getset rather than its
+ // tp_members to set up __doc__ and __name__, because tp_members
+ // really depends on having a POD object type (it relies on
+ // offsets). It might make sense to reformulate function as a POD
+ // at some point, but this is much more expedient.
+ //
+ static PyObject* proxy_method_get_doc(PyObject* op, void*) {
+ proxy_method* self = downcast<proxy_method>(op);
+ return ::PyObject_GetAttrString(self->target, "__doc__");
+ }
+
+ static int proxy_method_set_doc(PyObject* op, PyObject* doc, void*) {
+ proxy_method* self = downcast<proxy_method>(op);
+ return ::PyObject_SetAttrString(self->target, "__doc__", doc);
+ }
+
+ static PyObject* proxy_method_get_name(PyObject* op, void*) {
+ proxy_method* self = downcast<proxy_method>(op);
+ return ::PyObject_GetAttrString(self->target, "__name__");
+ }
+
+ // We add a dummy __class__ attribute in order to fool PyDoc into
+ // treating these as built-in functions and scanning their
+ // documentation
+ static PyObject* proxy_method_get_class(PyObject* /*op*/, void*) {
+ return python::incref(upcast<PyObject>(&PyCFunction_Type));
+ }
 }
 
-}}}
-
-class Example {
-public:
- std::size_t get_address() const { return std::size_t(this); }
-
- bool non_const_method() { return true; }
-
- bool const_method() const { return true; }
+static PyGetSetDef proxy_method_getsetlist[] = {
+ {const_cast<char*>("__name__"), (getter)proxy_method_get_name, 0, 0, 0 },
+ {const_cast<char*>("func_name"), (getter)proxy_method_get_name, 0, 0, 0 },
+ {const_cast<char*>("__class__"), (getter)proxy_method_get_class, 0, 0, 0 }, // see note above
+ {const_cast<char*>("__doc__"), (getter)proxy_method_get_doc, (setter)proxy_method_set_doc, 0, 0},
+ {const_cast<char*>("func_doc"), (getter)proxy_method_get_doc, (setter)proxy_method_set_doc, 0, 0},
+ {NULL, 0, 0, 0, 0} /* Sentinel */
 };
 
-class Owner {
-public:
- Example by_value() const { return _example; }
- Example const by_const_value() const { return _example; }
- Example & by_reference() { return _example; }
- Example const & by_const_reference() const { return _example; }
-private:
- Example _example;
+PyTypeObject proxy_method_type_object = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ const_cast<char*>("Boost.Python.proxy_method"),
+ sizeof(proxy_method),
+ 0,
+ (destructor)proxy_method_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, //(reprfunc)func_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ proxy_method_call, /* tp_call */
+ 0, /* tp_str */
+ 0, // PyObject_GenericGetAttr, /* tp_getattro */
+ 0, // PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */
+ 0, /* tp_doc */
+ 0, // (traverseproc)func_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, // func_memberlist, /* tp_members */
+ proxy_method_getsetlist, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ proxy_method_descr_get, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#if PYTHON_API_VERSION >= 1012
+ 0 /* tp_del */
+#endif
 };
 
-static void export_module() {
-
- bp::const_aware_class<Example>("Example", "FrozenExample")
- .add_property("address", &Example::get_address)
- .def("non_const_method", &Example::non_const_method)
- .def("const_method", &Example::const_method)
- ;
-
- bp::class_<Owner>("Owner")
- .def("by_value", &Owner::by_value)
- .def("by_const_value", &Owner::by_const_value)
- .def("by_reference", &Owner::by_reference, bp::return_internal_reference<>())
- .def("by_const_reference", &Owner::by_const_reference, bp::return_internal_const_reference<>())
- ;
+type_handle proxy_method_type() {
+ if (proxy_method_type_object.tp_dict == 0) {
+ if (PyType_Ready(&proxy_method_type_object))
+ return type_handle();
+ }
+ return type_handle(borrowed(&proxy_method_type_object));
+}
 
+object make_proxy_method(object const & target) {
+ if (!PyCallable_Check(target.ptr())) {
+ PyErr_SetString(PyExc_TypeError, "proxy_method target must be callable");
+ throw_error_already_set();
+ }
+ PyObject * raw_proxy = proxy_method_type()->tp_alloc(proxy_method_type().get(), 0);
+ if (raw_proxy != 0) {
+ proxy_method * self = (proxy_method*)raw_proxy;
+ self->target = python::incref(target.ptr());
+ }
+ return object(handle<>(raw_proxy));
 }
 
-BOOST_PYTHON_MODULE(const_aware) {
- export_module();
+object make_proxy_property(object const & target) {
+ object old_fget = target.attr("fget");
+ object doc = target.attr("__doc__");
+ object new_fget = make_proxy_method(old_fget);
+ object result(
+ (python::detail::new_reference)
+ PyObject_CallFunction((PyObject*)&PyProperty_Type,
+ const_cast<char*>("Osss"), new_fget.ptr(), 0, 0, doc.ptr())
+ );
+ return result;
 }
+
+}}} // namespace boost::python::const_aware

Copied: sandbox/python_extensions/libs/python/src/registry.cpp (from r62162, /sandbox/python_extensions/libs/python/test/const_aware.cpp)
==============================================================================
--- /sandbox/python_extensions/libs/python/test/const_aware.cpp (original)
+++ sandbox/python_extensions/libs/python/src/registry.cpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,71 +1,35 @@
+// Copyright 2010 Jim Bosch
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
 #include <boost/python.hpp>
-#include <boost/python/const_aware_class.hpp>
+#include <boost/python/const_aware/registry.hpp>
+#include <boost/python/const_aware/proxy_class.hpp>
+#include <boost/python/const_aware/as_const.hpp>
 
-#include <iostream>
 #include <map>
 
-namespace bp = boost::python;
-
-namespace boost { namespace python { namespace const_aware_registry {
+namespace boost { namespace python { namespace const_aware { namespace registry {
 
 namespace {
+
 typedef std::map<PyTypeObject*,PyTypeObject*> registry_t;
-registry_t registry;
+registry_t & entries() {
+ static registry_t result;
+ return result;
 }
 
-PyTypeObject * lookup(PyTypeObject* non_const) {
- registry_t::const_iterator iter = registry.find(non_const);
- if (iter != registry.end()) return iter->second;
- return NULL;
 }
 
-void insert(object const & non_const, object const & const_) {
- registry.insert(
- registry_t::value_type(
- reinterpret_cast<PyTypeObject*>(non_const.ptr()),
- reinterpret_cast<PyTypeObject*>(const_.ptr())
- )
- );
+PyTypeObject * query(PyTypeObject const * non_const) {
+ registry_t::const_iterator iter = entries().find(const_cast<PyTypeObject*>(non_const));
+ if (iter != entries().end()) return iter->second;
+ return 0;
 }
 
-}}}
-
-class Example {
-public:
- std::size_t get_address() const { return std::size_t(this); }
-
- bool non_const_method() { return true; }
-
- bool const_method() const { return true; }
-};
-
-class Owner {
-public:
- Example by_value() const { return _example; }
- Example const by_const_value() const { return _example; }
- Example & by_reference() { return _example; }
- Example const & by_const_reference() const { return _example; }
-private:
- Example _example;
-};
-
-static void export_module() {
-
- bp::const_aware_class<Example>("Example", "FrozenExample")
- .add_property("address", &Example::get_address)
- .def("non_const_method", &Example::non_const_method)
- .def("const_method", &Example::const_method)
- ;
-
- bp::class_<Owner>("Owner")
- .def("by_value", &Owner::by_value)
- .def("by_const_value", &Owner::by_const_value)
- .def("by_reference", &Owner::by_reference, bp::return_internal_reference<>())
- .def("by_const_reference", &Owner::by_const_reference, bp::return_internal_const_reference<>())
- ;
-
+void insert(PyTypeObject * non_const, PyTypeObject * const_) {
+ entries().insert(registry_t::value_type(non_const, const_));
 }
 
-BOOST_PYTHON_MODULE(const_aware) {
- export_module();
-}
+}}}} // namespace boost::python::const_aware::registry

Modified: sandbox/python_extensions/libs/python/test/SConscript
==============================================================================
--- sandbox/python_extensions/libs/python/test/SConscript (original)
+++ sandbox/python_extensions/libs/python/test/SConscript 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,7 +1,8 @@
 Import("bp_extensions_env")
 
 test_mod = bp_extensions_env.SharedLibrary("test_mod", "test_mod.cpp", SHLIBPREFIX="")
-const_aware_mod = bp_extensions_env.SharedLibrary("const_aware", "const_aware.cpp", SHLIBPREFIX="")
+const_aware_mod = bp_extensions_env.SharedLibrary("const_aware", "const_aware.cpp", SHLIBPREFIX="",
+ LIBS="boost_python_extensions")
 test = (
     bp_extensions_env.PythonUnitTest("test_script.py", test_mod)
     + bp_extensions_env.PythonUnitTest("const_aware.py", const_aware_mod)

Modified: sandbox/python_extensions/libs/python/test/const_aware.cpp
==============================================================================
--- sandbox/python_extensions/libs/python/test/const_aware.cpp (original)
+++ sandbox/python_extensions/libs/python/test/const_aware.cpp 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -1,67 +1,73 @@
 #include <boost/python.hpp>
-#include <boost/python/const_aware_class.hpp>
-
-#include <iostream>
-#include <map>
+#include <boost/python/const_aware.hpp>
+#include <boost/shared_ptr.hpp>
 
 namespace bp = boost::python;
 
-namespace boost { namespace python { namespace const_aware_registry {
-
-namespace {
-typedef std::map<PyTypeObject*,PyTypeObject*> registry_t;
-registry_t registry;
-}
-
-PyTypeObject * lookup(PyTypeObject* non_const) {
- registry_t::const_iterator iter = registry.find(non_const);
- if (iter != registry.end()) return iter->second;
- return NULL;
-}
-
-void insert(object const & non_const, object const & const_) {
- registry.insert(
- registry_t::value_type(
- reinterpret_cast<PyTypeObject*>(non_const.ptr()),
- reinterpret_cast<PyTypeObject*>(const_.ptr())
- )
- );
-}
-
-}}}
-
 class Example {
 public:
+ Example() : value(0) {}
+
     std::size_t get_address() const { return std::size_t(this); }
 
     bool non_const_method() { return true; }
-
     bool const_method() const { return true; }
+
+ int value;
+
+ int get_value() const { return value; }
+ void set_value(int v) { value = v; }
 };
 
 class Owner {
 public:
- Example by_value() const { return _example; }
- Example const by_const_value() const { return _example; }
- Example & by_reference() { return _example; }
- Example const & by_const_reference() const { return _example; }
+ Example by_value() const { return *_example; }
+ Example const by_const_value() const { return *_example; }
+ Example & by_reference() { return *_example; }
+ Example const & by_const_reference() const { return *_example; }
+ boost::shared_ptr<Example> by_shared_ptr() { return _example; }
+ boost::shared_ptr<Example const> by_const_shared_ptr() const { return _example; }
+
+ bool accept_by_value(Example x) { return true; }
+ bool accept_by_const_value(Example const x) { return true; }
+ bool accept_by_reference(Example & x) { return true; }
+ bool accept_by_const_reference(Example const & x) { return true; }
+ bool accept_by_shared_ptr(boost::shared_ptr<Example> const & x) { return true; }
+ bool accept_by_const_shared_ptr(boost::shared_ptr<Example const> const & x) { return true; }
+
+ explicit Owner() : _example(new Example()) {}
 private:
- Example _example;
+ boost::shared_ptr<Example> _example;
 };
 
 static void export_module() {
-
- bp::const_aware_class<Example>("Example", "FrozenExample")
+
+ bp::class_<Example> pyExample("Example");
+
+ bp::make_const_aware(pyExample, "FrozenExample")
         .add_property("address", &Example::get_address)
         .def("non_const_method", &Example::non_const_method)
         .def("const_method", &Example::const_method)
+ .add_property("value_prop", &Example::get_value, &Example::set_value)
+ .def_readonly("value_ro", &Example::value)
+ .def_readwrite("value_rw", &Example::value)
+ .enable_shared_ptr();
         ;
 
     bp::class_<Owner>("Owner")
         .def("by_value", &Owner::by_value)
- .def("by_const_value", &Owner::by_const_value)
+ .def("by_const_value", &Owner::by_const_value, bp::as_const<>())
         .def("by_reference", &Owner::by_reference, bp::return_internal_reference<>())
- .def("by_const_reference", &Owner::by_const_reference, bp::return_internal_const_reference<>())
+ .def("by_const_reference", &Owner::by_const_reference,
+ bp::as_const< bp::return_internal_reference<> >())
+ .def("by_shared_ptr", &Owner::by_shared_ptr)
+ .def("by_const_shared_ptr", &Owner::by_const_shared_ptr)
+ .def("accept_by_value", &Owner::accept_by_value)
+ .def("accept_by_const_value", &Owner::accept_by_const_value)
+ .def("accept_by_reference", &Owner::accept_by_reference)
+ .def("accept_by_const_reference", &Owner::accept_by_const_reference)
+ .def("accept_by_shared_ptr", &Owner::accept_by_shared_ptr)
+ .def("accept_by_const_shared_ptr", &Owner::accept_by_const_shared_ptr)
         ;
 
 }

Modified: sandbox/python_extensions/libs/python/test/const_aware.py
==============================================================================
--- sandbox/python_extensions/libs/python/test/const_aware.py (original)
+++ sandbox/python_extensions/libs/python/test/const_aware.py 2010-05-25 04:50:07 EDT (Tue, 25 May 2010)
@@ -6,26 +6,74 @@
     def setUp(self):
         self.owner = const_aware.Owner()
 
+ def checkNonConst(self, x):
+ self.assertEqual(type(x), const_aware.Example)
+ self.assert_(x.const_method())
+ self.assert_(x.non_const_method())
+ self.assert_(self.owner.accept_by_value(x))
+ self.assert_(self.owner.accept_by_const_value(x))
+ self.assert_(self.owner.accept_by_reference(x))
+ self.assert_(self.owner.accept_by_const_reference(x))
+ self.assert_(self.owner.accept_by_shared_ptr(x))
+ self.assert_(self.owner.accept_by_const_shared_ptr(x))
+ self.assertEqual(x.value_prop, 0)
+ self.assertEqual(x.value_ro, 0)
+ self.assertEqual(x.value_rw, 0)
+ x.value_prop = 1
+ self.assertEqual(x.value_prop, 1)
+ self.assertEqual(x.value_ro, 1)
+ self.assertEqual(x.value_rw, 1)
+ x.value_rw = 0
+ self.assertEqual(x.value_prop, 0)
+ self.assertEqual(x.value_ro, 0)
+ self.assertEqual(x.value_rw, 0)
+ def set_value_ro(v):
+ x.value_ro = v
+ self.assertRaises(AttributeError, set_value_ro, 1)
+
+ def checkConst(self, x):
+ self.assertEqual(type(x), const_aware.FrozenExample)
+ self.assert_(x.const_method())
+ self.assertFalse(hasattr(x,"non_const_method"))
+ self.assert_(self.owner.accept_by_value(x))
+ self.assert_(self.owner.accept_by_const_value(x))
+ self.assertRaises(Exception, self.owner.accept_by_reference, x)
+ self.assert_(self.owner.accept_by_const_reference(x))
+ self.assertRaises(Exception, self.owner.accept_by_shared_ptr, x)
+ self.assert_(self.owner.accept_by_const_shared_ptr(x))
+ self.assertEqual(x.value_prop, 0)
+ self.assertEqual(x.value_ro, 0)
+ self.assertEqual(x.value_rw, 0)
+ def set_value_prop(v):
+ x.value_prop = v
+ def set_value_rw(v):
+ x.value_rw = v
+ def set_value_ro(v):
+ x.value_ro = v
+ self.assertRaises(AttributeError, set_value_prop, 1)
+ self.assertRaises(AttributeError, set_value_rw, 1)
+ self.assertRaises(AttributeError, set_value_ro, 1)
+
     def testByValue(self):
- by_value = self.owner.by_value();
- by_const_value = self.owner.by_const_value();
- self.assertEqual(type(by_value), const_aware.Example)
+ by_value = self.owner.by_value()
+ by_const_value = self.owner.by_const_value()
         self.assertNotEqual(by_value.address, by_const_value.address)
- self.assert_(by_value.const_method())
- self.assert_(by_const_value.const_method())
- self.assert_(by_value.non_const_method())
- self.assert_(by_const_value.non_const_method())
+ self.checkNonConst(by_value)
+ self.checkConst(by_const_value)
 
     def testByReference(self):
- by_reference = self.owner.by_reference();
- by_const_reference = self.owner.by_const_reference();
- self.assertEqual(type(by_reference), const_aware.Example)
- self.assertEqual(type(by_const_reference), const_aware.FrozenExample)
+ by_reference = self.owner.by_reference()
+ by_const_reference = self.owner.by_const_reference()
         self.assertEqual(by_reference.address, by_const_reference.address)
- self.assert_(by_reference.const_method())
- self.assert_(by_const_reference.const_method())
- self.assert_(by_reference.non_const_method())
- self.assertFalse(hasattr(by_const_reference,"non_const_method"))
+ self.checkNonConst(by_reference)
+ self.checkConst(by_const_reference)
+
+ def testBySharedPtr(self):
+ by_shared_ptr = self.owner.by_shared_ptr();
+ by_const_shared_ptr = self.owner.by_const_shared_ptr();
+ self.assertEqual(by_shared_ptr.address, by_const_shared_ptr.address)
+ self.checkNonConst(by_shared_ptr)
+ self.checkConst(by_const_shared_ptr)
 
 if __name__=="__main__":
     unittest.main()


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk