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

Add the ability to easily use new-style polymorphism wrappers with

smart pointer held_type.


[SVN r31392]
This commit is contained in:
Dave Abrahams
2005-10-19 18:17:13 +00:00
parent c8a692b4b4
commit 12770b03e8
8 changed files with 160 additions and 16 deletions

View File

@@ -30,6 +30,10 @@
# include <boost/mpl/for_each.hpp>
# include <boost/mpl/placeholders.hpp>
# include <boost/mpl/single_view.hpp>
# include <boost/mpl/assert.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/noncopyable.hpp>
@@ -49,6 +53,8 @@ struct register_base_of
template <class Base>
inline void operator()(Base*) const
{
BOOST_MPL_ASSERT_NOT((is_same<Base,Derived>));
// Register the Base class
register_dynamic_id<Base>();
@@ -58,7 +64,7 @@ struct register_base_of
// Register the down-cast, if appropriate.
this->register_downcast((Base*)0, is_polymorphic<Base>());
}
private:
static inline void register_downcast(void*, mpl::false_) {}
@@ -186,7 +192,7 @@ struct class_metadata
, mpl::if_<
use_value_holder
, value_holder<T>
, pointer_holder<held_type,T>
, pointer_holder<held_type,wrapped>
>
>::type holder;
@@ -253,6 +259,8 @@ struct class_metadata
//
inline static void maybe_register_callback_class(void*, mpl::false_) {}
inline static void maybe_register_callback_class(wrapped*, mpl::true_) {}
template <class T2>
inline static void maybe_register_callback_class(T2*, mpl::true_)
{

View File

@@ -101,6 +101,10 @@ bpl-test crossmod_exception
[ bpl-test andreas_beyer ]
[ bpl-test polymorphism ]
[ bpl-test polymorphism2 ]
[ bpl-test wrapper_held_type ]
[ bpl-test polymorphism2_auto_ptr ]
[ bpl-test auto_ptr ]
[ bpl-test minimal ]
[ bpl-test args ]
@@ -115,7 +119,7 @@ bpl-test crossmod_exception
[ bpl-test keywords : keywords.cpp keywords_test.py ]
[ extension builtin_converters : test_builtin_converters.cpp <template>../build/extension ]
[ boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters ]
[ boost-python-runtest builtin_converters : test_builtin_converters.py <pyd>builtin_converters : : : -v ]
[ bpl-test test_pointer_adoption ]
[ bpl-test operators ]
@@ -164,11 +168,11 @@ bpl-test crossmod_exception
[ bpl-test vector_indexing_suite ]
[ bpl-test pointer_vector ]
[ extension map_indexing_suite_ext
: map_indexing_suite.cpp int_map_indexing_suite.cpp <template>../build/extension ]
[ boost-python-runtest
map_indexing_suite : map_indexing_suite.py <pyd>map_indexing_suite_ext ]
#[ boost-python-runtest
# map_indexing_suite : map_indexing_suite.py <pyd>map_indexing_suite_ext : : : -v ]
# if $(TEST_BIENSTMAN_NON_BUGS)
# {

View File

@@ -13,6 +13,14 @@
#include <boost/python/call.hpp>
#include <boost/utility.hpp>
#include <memory>
#ifdef HELD_BY_AUTO_PTR
# define HELD_PTR(X) , std::auto_ptr< X >
#else
# define HELD_PTR(X)
#endif
using namespace boost::python;
struct P
@@ -123,19 +131,23 @@ C& getCCppObj ()
A* pass_a(A* x) { return x; }
#ifdef HELD_BY_AUTO_PTR
BOOST_PYTHON_MODULE_INIT(polymorphism2_auto_ptr_ext)
#else
BOOST_PYTHON_MODULE_INIT(polymorphism2_ext)
#endif
{
class_<ACallback,boost::noncopyable>("A")
class_<ACallback HELD_PTR(A),boost::noncopyable>("A")
.def("f", &A::f, &ACallback::default_f)
;
def("getBCppObj", getBCppObj, return_value_policy<reference_existing_object>());
class_<C,bases<A>,boost::noncopyable>("C")
class_<C HELD_PTR(C),bases<A>,boost::noncopyable>("C")
.def("f", &C::f)
;
class_<DCallback,bases<A>,boost::noncopyable>("D")
class_<DCallback HELD_PTR(D),bases<A>,boost::noncopyable>("D")
.def("f", &D::f)
.def("g", &D::g)
;
@@ -152,7 +164,7 @@ BOOST_PYTHON_MODULE_INIT(polymorphism2_ext)
.def("f", pure_virtual(&P::f))
;
class_<Q, bases<P> >("Q")
class_<Q HELD_PTR(Q), bases<P> >("Q")
.def("g", &P::g) // make sure virtual inheritance doesn't interfere
;
}

View File

@@ -2,7 +2,7 @@
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import unittest
from polymorphism2_ext import *
import sys
class PolymorphTest(unittest.TestCase):
@@ -77,11 +77,18 @@ class PolymorphTest(unittest.TestCase):
r = R()
self.failUnlessEqual ('R.f', r.f())
if __name__ == "__main__":
# remove the option which upsets unittest
def test():
# remove the option that upsets unittest
import sys
sys.argv = [ x for x in sys.argv if x != '--broken-auto-ptr' ]
unittest.main()
# This nasty hack basically says that if we're loaded by another module, we'll
# be testing polymorphism2_auto_ptr_ext instead of polymorphism2_ext.
if __name__ == "__main__":
from polymorphism2_ext import *
test()
else:
from polymorphism2_auto_ptr_ext import *

View File

@@ -0,0 +1,6 @@
// Copyright David Abrahams 2005. 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)
#define HELD_BY_AUTO_PTR
#include "polymorphism2.cpp"

View File

@@ -0,0 +1,5 @@
# Copyright David Abrahams 2005. 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)
import polymorphism2
polymorphism2.test()

68
test/wrapper_held_type.cpp Executable file
View File

@@ -0,0 +1,68 @@
// Copyright David Abrahams 2005. 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/register_ptr_to_python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/wrapper.hpp>
#include <boost/python/module.hpp>
#include <boost/python/implicit.hpp>
#include <memory>
struct data
{
virtual int id() const
{
return 42;
}
};
std::auto_ptr<data> create_data()
{
return std::auto_ptr<data>( new data );
}
void do_nothing( std::auto_ptr<data>& ){}
namespace bp = boost::python;
struct data_wrapper : data, bp::wrapper< data >
{
data_wrapper(data const & arg )
: data( arg )
, bp::wrapper< data >()
{}
data_wrapper()
: data()
, bp::wrapper< data >()
{}
virtual int id() const
{
if( bp::override id = this->get_override( "id" ) )
return bp::call<int>(id.ptr()); // id();
else
return data::id( );
}
virtual int default_id( ) const
{
return this->data::id( );
}
};
BOOST_PYTHON_MODULE(wrapper_held_type_ext)
{
bp::class_< data_wrapper, std::auto_ptr< data > >( "data" )
.def( "id", &data::id, &::data_wrapper::default_id );
bp::def( "do_nothing", &do_nothing );
bp::def( "create_data", &create_data );
}
#include "module_tail.cpp"

34
test/wrapper_held_type.py Normal file
View File

@@ -0,0 +1,34 @@
# Copyright David Abrahams 2005. 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)
'''
>>> from wrapper_held_type_ext import *
>>> d = data()
>>> print d.id()
42
>>> do_nothing( d )
>>> print d.id()
42
>>> d = create_data()
>>> print d.id()
42
>>> do_nothing( d )
>>> print d.id()
42
'''
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
status = run()[0]
if (status == 0): print "Done."
sys.exit(status)