os/ossrv/ossrv_pub/boost_apis/boost/python/class.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright David Abrahams 2002.
     2 // Distributed under the Boost Software License, Version 1.0. (See
     3 // accompanying file LICENSE_1_0.txt or copy at
     4 // http://www.boost.org/LICENSE_1_0.txt)
     5 #ifndef CLASS_DWA200216_HPP
     6 # define CLASS_DWA200216_HPP
     7 
     8 # include <boost/python/detail/prefix.hpp>
     9 
    10 # include <boost/noncopyable.hpp>
    11 
    12 # include <boost/python/class_fwd.hpp>
    13 # include <boost/python/object/class.hpp>
    14 
    15 # include <boost/python/object.hpp>
    16 # include <boost/python/type_id.hpp>
    17 # include <boost/python/data_members.hpp>
    18 # include <boost/python/make_function.hpp>
    19 # include <boost/python/signature.hpp>
    20 # include <boost/python/init.hpp>
    21 # include <boost/python/args_fwd.hpp>
    22 
    23 # include <boost/python/object/class_metadata.hpp>
    24 # include <boost/python/object/pickle_support.hpp>
    25 # include <boost/python/object/add_to_namespace.hpp>
    26 
    27 # include <boost/python/detail/overloads_fwd.hpp>
    28 # include <boost/python/detail/operator_id.hpp>
    29 # include <boost/python/detail/def_helper.hpp>
    30 # include <boost/python/detail/force_instantiate.hpp>
    31 # include <boost/python/detail/unwrap_type_id.hpp>
    32 # include <boost/python/detail/unwrap_wrapper.hpp>
    33 
    34 # include <boost/type_traits/is_same.hpp>
    35 # include <boost/type_traits/is_member_function_pointer.hpp>
    36 # include <boost/type_traits/is_polymorphic.hpp>
    37 
    38 # include <boost/mpl/size.hpp>
    39 # include <boost/mpl/for_each.hpp>
    40 # include <boost/mpl/bool.hpp>
    41 # include <boost/mpl/not.hpp>
    42 
    43 # include <boost/detail/workaround.hpp>
    44 
    45 # if BOOST_WORKAROUND(__MWERKS__, <= 0x3004)                        \
    46     /* pro9 reintroduced the bug */                                 \
    47     || (BOOST_WORKAROUND(__MWERKS__, > 0x3100)                      \
    48         && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))   \
    49     || BOOST_WORKAROUND(__GNUC__, < 3)
    50 
    51 #  define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1
    52 
    53 # endif
    54 
    55 # ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
    56 #  include <boost/mpl/and.hpp>
    57 #  include <boost/type_traits/is_member_pointer.hpp>
    58 # endif
    59 
    60 namespace boost { namespace python {
    61 
    62 template <class DerivedVisitor> class def_visitor;
    63 
    64 enum no_init_t { no_init };
    65 
    66 namespace detail
    67 {
    68   // This function object is used with mpl::for_each to write the id
    69   // of the type a pointer to which is passed as its 2nd compile-time
    70   // argument. into the iterator pointed to by its runtime argument
    71   struct write_type_id
    72   {
    73       write_type_id(type_info**p) : p(p) {}
    74 
    75       // Here's the runtime behavior
    76       template <class T>
    77       void operator()(T*) const
    78       {
    79           *(*p)++ = type_id<T>();
    80       }
    81 
    82       type_info** p;
    83   };
    84 
    85   template <class T>
    86   struct is_data_member_pointer
    87       : mpl::and_<
    88             is_member_pointer<T>
    89           , mpl::not_<is_member_function_pointer<T> >
    90         >
    91   {};
    92   
    93 # ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
    94 #  define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
    95 #  define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
    96 #  define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
    97 # elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
    98 #  define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
    99 #  define BOOST_PYTHON_YES_DATA_MEMBER , int
   100 #  define BOOST_PYTHON_NO_DATA_MEMBER , ...
   101 # else 
   102 #  define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
   103 #  define BOOST_PYTHON_YES_DATA_MEMBER
   104 #  define BOOST_PYTHON_NO_DATA_MEMBER
   105 # endif
   106   
   107   namespace error
   108   {
   109     //
   110     // A meta-assertion mechanism which prints nice error messages and
   111     // backtraces on lots of compilers. Usage:
   112     //
   113     //      assertion<C>::failed
   114     //
   115     // where C is an MPL metafunction class
   116     //
   117     
   118     template <class C> struct assertion_failed { };
   119     template <class C> struct assertion_ok { typedef C failed; };
   120 
   121     template <class C>
   122     struct assertion
   123         : mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type
   124     {};
   125 
   126     //
   127     // Checks for validity of arguments used to define virtual
   128     // functions with default implementations.
   129     //
   130     
   131     template <class Default>
   132     void not_a_derived_class_member(Default) {}
   133     
   134     template <class T, class Fn>
   135     struct virtual_function_default
   136     {
   137         template <class Default>
   138         static void
   139         must_be_derived_class_member(Default const&)
   140         {
   141             typedef typename assertion<mpl::not_<is_same<Default,Fn> > >::failed test0;
   142 # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
   143             typedef typename assertion<is_polymorphic<T> >::failed test1;
   144 # endif 
   145             typedef typename assertion<is_member_function_pointer<Fn> >::failed test2;
   146             not_a_derived_class_member<Default>(Fn());
   147         }
   148     };
   149   }
   150 }
   151 
   152 // This is the primary mechanism through which users will expose
   153 // C++ classes to Python.
   154 template <
   155     class W // class being wrapped
   156     , class X1 // = detail::not_specified
   157     , class X2 // = detail::not_specified
   158     , class X3 // = detail::not_specified
   159     >
   160 class class_ : public objects::class_base
   161 {
   162  public: // types
   163     typedef objects::class_base base;
   164     typedef class_<W,X1,X2,X3> self;
   165     typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
   166     typedef W wrapped_type;
   167     
   168  private: // types
   169 
   170     // A helper class which will contain an array of id objects to be
   171     // passed to the base class constructor
   172     struct id_vector
   173     {
   174         typedef typename metadata::bases bases;
   175         
   176         id_vector()
   177         {
   178             // Stick the derived class id into the first element of the array
   179             ids[0] = detail::unwrap_type_id((W*)0, (W*)0);
   180 
   181             // Write the rest of the elements into succeeding positions.
   182             type_info* p = ids + 1;
   183             mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0);
   184         }
   185 
   186         BOOST_STATIC_CONSTANT(
   187             std::size_t, size = mpl::size<bases>::value + 1);
   188         type_info ids[size];
   189     };
   190     friend struct id_vector;
   191 
   192  public: // constructors
   193     
   194     // Construct with the class name, with or without docstring, and default __init__() function
   195     class_(char const* name, char const* doc = 0);
   196 
   197     // Construct with class name, no docstring, and an uncallable __init__ function
   198     class_(char const* name, no_init_t);
   199 
   200     // Construct with class name, docstring, and an uncallable __init__ function
   201     class_(char const* name, char const* doc, no_init_t);
   202 
   203     // Construct with class name and init<> function
   204     template <class DerivedT>
   205     inline class_(char const* name, init_base<DerivedT> const& i)
   206         : base(name, id_vector::size, id_vector().ids)
   207     {
   208         this->initialize(i);
   209     }
   210 
   211     // Construct with class name, docstring and init<> function
   212     template <class DerivedT>
   213     inline class_(char const* name, char const* doc, init_base<DerivedT> const& i)
   214         : base(name, id_vector::size, id_vector().ids, doc)
   215     {
   216         this->initialize(i);
   217     }
   218 
   219  public: // member functions
   220     
   221     // Generic visitation
   222     template <class Derived>
   223     self& def(def_visitor<Derived> const& visitor)
   224     {
   225         visitor.visit(*this);
   226         return *this;
   227     }
   228 
   229     // Wrap a member function or a non-member function which can take
   230     // a T, T cv&, or T cv* as its first parameter, a callable
   231     // python object, or a generic visitor.
   232     template <class F>
   233     self& def(char const* name, F f)
   234     {
   235         this->def_impl(
   236             detail::unwrap_wrapper((W*)0)
   237           , name, f, detail::def_helper<char const*>(0), &f);
   238         return *this;
   239     }
   240 
   241     template <class A1, class A2>
   242     self& def(char const* name, A1 a1, A2 const& a2)
   243     {
   244         this->def_maybe_overloads(name, a1, a2, &a2);
   245         return *this;
   246     }
   247 
   248     template <class Fn, class A1, class A2>
   249     self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
   250     {
   251         //  The arguments are definitely:
   252         //      def(name, function, policy, doc_string)
   253         //      def(name, function, doc_string, policy)
   254 
   255         this->def_impl(
   256             detail::unwrap_wrapper((W*)0)
   257           , name, fn
   258           , detail::def_helper<A1,A2>(a1,a2)
   259           , &fn);
   260 
   261         return *this;
   262     }
   263 
   264     template <class Fn, class A1, class A2, class A3>
   265     self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
   266     {
   267         this->def_impl(
   268             detail::unwrap_wrapper((W*)0)
   269           , name, fn
   270           , detail::def_helper<A1,A2,A3>(a1,a2,a3)
   271           , &fn);
   272 
   273         return *this;
   274     }
   275 
   276     //
   277     // Data member access
   278     //
   279     template <class D>
   280     self& def_readonly(char const* name, D const& d, char const* doc=0)
   281     {
   282         return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
   283     }
   284 
   285     template <class D>
   286     self& def_readwrite(char const* name, D const& d, char const* doc=0)
   287     {
   288         return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
   289     }
   290     
   291     template <class D>
   292     self& def_readonly(char const* name, D& d, char const* doc=0)
   293     {
   294         return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
   295     }
   296 
   297     template <class D>
   298     self& def_readwrite(char const* name, D& d, char const* doc=0)
   299     {
   300         return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
   301     }
   302 
   303     // Property creation
   304 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
   305     template <class Get>
   306     self& add_property(char const* name, Get fget, char const* docstr = 0)
   307     {
   308         base::add_property(name, this->make_getter(fget), docstr);
   309         return *this;
   310     }
   311 
   312     template <class Get, class Set>
   313     self& add_property(char const* name, Get fget, Set fset, char const* docstr = 0)
   314     {
   315         base::add_property(
   316             name, this->make_getter(fget), this->make_setter(fset), docstr);
   317         return *this;
   318     }
   319 # else
   320  private:
   321     template <class Get>
   322     self& add_property_impl(char const* name, Get fget, char const* docstr, int)
   323     {
   324         base::add_property(name, this->make_getter(fget), docstr);
   325         return *this;
   326     }
   327 
   328     template <class Get, class Set>
   329     self& add_property_impl(char const* name, Get fget, Set fset, ...)
   330     {
   331         base::add_property(
   332             name, this->make_getter(fget), this->make_setter(fset), 0);
   333         return *this;
   334     }
   335 
   336  public:    
   337     template <class Get>
   338     self& add_property(char const* name, Get fget)
   339     {
   340         base::add_property(name, this->make_getter(fget), 0);
   341         return *this;
   342     }
   343 
   344     template <class Get, class DocStrOrSet>
   345     self& add_property(char const* name, Get fget, DocStrOrSet docstr_or_set)
   346     {
   347         this->add_property_impl(name, this->make_getter(fget), docstr_or_set, 0);
   348         return *this;
   349     }
   350 
   351     template <class Get, class Set>
   352     self&
   353     add_property(char const* name, Get fget, Set fset, char const* docstr)
   354     {
   355         base::add_property(
   356             name, this->make_getter(fget), this->make_setter(fset), docstr);
   357         return *this;
   358     }
   359 # endif
   360         
   361     template <class Get>
   362     self& add_static_property(char const* name, Get fget)
   363     {
   364         base::add_static_property(name, object(fget));
   365         return *this;
   366     }
   367 
   368     template <class Get, class Set>
   369     self& add_static_property(char const* name, Get fget, Set fset)
   370     {
   371         base::add_static_property(name, object(fget), object(fset));
   372         return *this;
   373     }
   374         
   375     template <class U>
   376     self& setattr(char const* name, U const& x)
   377     {
   378         this->base::setattr(name, object(x));
   379         return *this;
   380     }
   381 
   382     // Pickle support
   383     template <typename PickleSuiteType>
   384     self& def_pickle(PickleSuiteType const& x)
   385     {
   386       error_messages::must_be_derived_from_pickle_suite(x);
   387       detail::pickle_suite_finalize<PickleSuiteType>::register_(
   388         *this,
   389         &PickleSuiteType::getinitargs,
   390         &PickleSuiteType::getstate,
   391         &PickleSuiteType::setstate,
   392         PickleSuiteType::getstate_manages_dict());
   393       return *this;
   394     }
   395 
   396     self& enable_pickling()
   397     {
   398         this->base::enable_pickling_(false);
   399         return *this;
   400     }
   401 
   402     self& staticmethod(char const* name)
   403     {
   404         this->make_method_static(name);
   405         return *this;
   406     }
   407  private: // helper functions
   408 
   409     // Builds a method for this class around the given [member]
   410     // function pointer or object, appropriately adjusting the type of
   411     // the first signature argument so that if f is a member of a
   412     // (possibly not wrapped) base class of T, an lvalue argument of
   413     // type T will be required.
   414     //
   415     // @group PropertyHelpers {
   416     template <class F>
   417     object make_getter(F f)
   418     {
   419         typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
   420         
   421         return this->make_fn_impl(
   422             detail::unwrap_wrapper((W*)0)
   423           , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
   424         );
   425     }
   426     
   427     template <class F>
   428     object make_setter(F f)
   429     {
   430         typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
   431         
   432         return this->make_fn_impl(
   433             detail::unwrap_wrapper((W*)0)
   434           , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
   435         );
   436     }
   437     
   438     template <class T, class F>
   439     object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_)
   440     {
   441         return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
   442     }
   443 
   444     template <class T, class D, class B>
   445     object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_)
   446     {
   447         D T::*pm = pm_;
   448         return python::make_getter(pm);
   449     }
   450 
   451     template <class T, class D, class B>
   452     object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_)
   453     {
   454         D T::*pm = pm_;
   455         return python::make_setter(pm);
   456     }
   457 
   458     template <class T, class F>
   459     object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_)
   460     {
   461         return x;
   462     }
   463     // }
   464     
   465     template <class D, class B>
   466     self& def_readonly_impl(
   467         char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
   468     {
   469         return this->add_property(name, pm_, doc);
   470     }
   471 
   472     template <class D, class B>
   473     self& def_readwrite_impl(
   474         char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
   475     {
   476         return this->add_property(name, pm_, pm_, doc);
   477     }
   478 
   479     template <class D>
   480     self& def_readonly_impl(
   481         char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
   482     {
   483         return this->add_static_property(name, python::make_getter(d));
   484     }
   485 
   486     template <class D>
   487     self& def_readwrite_impl(
   488         char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
   489     {
   490         return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
   491     }
   492 
   493     template <class DefVisitor>
   494     inline void initialize(DefVisitor const& i)
   495     {
   496         metadata::register_(); // set up runtime metadata/conversions
   497         
   498         typedef typename metadata::holder holder;
   499         this->set_instance_size( objects::additional_instance_size<holder>::value );
   500         
   501         this->def(i);
   502     }
   503     
   504     inline void initialize(no_init_t)
   505     {
   506         metadata::register_(); // set up runtime metadata/conversions
   507         this->def_no_init();
   508     }
   509     
   510     //
   511     // These two overloads discriminate between def() as applied to a
   512     // generic visitor and everything else.
   513     //
   514     // @group def_impl {
   515     template <class T, class Helper, class LeafVisitor, class Visitor>
   516     inline void def_impl(
   517         T*
   518       , char const* name
   519       , LeafVisitor
   520       , Helper const& helper
   521       , def_visitor<Visitor> const* v
   522     )
   523     {
   524         v->visit(*this, name,  helper);
   525     }
   526 
   527     template <class T, class Fn, class Helper>
   528     inline void def_impl(
   529         T*
   530       , char const* name
   531       , Fn fn
   532       , Helper const& helper
   533       , ...
   534     )
   535     {
   536         objects::add_to_namespace(
   537             *this
   538           , name
   539           , make_function(
   540                 fn
   541               , helper.policies()
   542               , helper.keywords()
   543               , detail::get_signature(fn, (T*)0)
   544             )
   545           , helper.doc()
   546         );
   547 
   548         this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
   549     }
   550     // }
   551 
   552     //
   553     // These two overloads handle the definition of default
   554     // implementation overloads for virtual functions. The second one
   555     // handles the case where no default implementation was specified.
   556     //
   557     // @group def_default {
   558     template <class Fn, class Helper>
   559     inline void def_default(
   560         char const* name
   561         , Fn
   562         , Helper const& helper
   563         , mpl::bool_<true>)
   564     {
   565         detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
   566             helper.default_implementation());
   567             
   568         objects::add_to_namespace(
   569             *this, name,
   570             make_function(
   571                 helper.default_implementation(), helper.policies(), helper.keywords())
   572             );
   573     }
   574     
   575     template <class Fn, class Helper>
   576     inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
   577     { }
   578     // }
   579     
   580     //
   581     // These two overloads discriminate between def() as applied to
   582     // regular functions and def() as applied to the result of
   583     // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
   584     // discriminate.
   585     //
   586     // @group def_maybe_overloads {
   587     template <class OverloadsT, class SigT>
   588     void def_maybe_overloads(
   589         char const* name
   590         , SigT sig
   591         , OverloadsT const& overloads
   592         , detail::overloads_base const*)
   593 
   594     {
   595         //  convert sig to a type_list (see detail::get_signature in signature.hpp)
   596         //  before calling detail::define_with_defaults.
   597         detail::define_with_defaults(
   598             name, overloads, *this, detail::get_signature(sig));
   599     }
   600 
   601     template <class Fn, class A1>
   602     void def_maybe_overloads(
   603         char const* name
   604         , Fn fn
   605         , A1 const& a1
   606         , ...)
   607     {
   608         this->def_impl(
   609             detail::unwrap_wrapper((W*)0)
   610           , name
   611           , fn
   612           , detail::def_helper<A1>(a1)
   613           , &fn
   614         );
   615 
   616     }
   617     // }
   618 };
   619 
   620 
   621 //
   622 // implementations
   623 //
   624 
   625 template <class W, class X1, class X2, class X3>
   626 inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc)
   627     : base(name, id_vector::size, id_vector().ids, doc)
   628 {
   629     this->initialize(init<>());
   630 //  select_holder::assert_default_constructible();
   631 }
   632 
   633 template <class W, class X1, class X2, class X3>
   634 inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t)
   635     : base(name, id_vector::size, id_vector().ids)
   636 {
   637     this->initialize(no_init);
   638 }
   639 
   640 template <class W, class X1, class X2, class X3>
   641 inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
   642     : base(name, id_vector::size, id_vector().ids, doc)
   643 {
   644     this->initialize(no_init);
   645 }
   646 
   647 }} // namespace boost::python
   648 
   649 # undef BOOST_PYTHON_DATA_MEMBER_HELPER
   650 # undef BOOST_PYTHON_YES_DATA_MEMBER
   651 # undef BOOST_PYTHON_NO_DATA_MEMBER
   652 # undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
   653 
   654 #endif // CLASS_DWA200216_HPP