Revision: 559
http://svn.sourceforge.net/pygccxml/?rev=559&view=rev
Author: roman_yakovenko
Date: 2006-09-19 13:42:37 -0700 (Tue, 19 Sep 2006)
Log Message:
-----------
adding full custom smart ptr example
Modified Paths:
--------------
pyplusplus_dev/unittests/smart_ptrs/sconstruct
pyplusplus_dev/unittests/smart_ptrs/test.py
Added Paths:
-----------
pyplusplus_dev/unittests/smart_ptrs/bindings.cpp
pyplusplus_dev/unittests/smart_ptrs/classes.hpp
pyplusplus_dev/unittests/smart_ptrs/smart_ptr.h
Added: pyplusplus_dev/unittests/smart_ptrs/bindings.cpp
===================================================================
--- pyplusplus_dev/unittests/smart_ptrs/bindings.cpp (rev 0)
+++ pyplusplus_dev/unittests/smart_ptrs/bindings.cpp 2006-09-19 20:42:37 UTC (rev 559)
@@ -0,0 +1,85 @@
+// This file has been generated by Py++.
+
+// Copyright 2004 Roman Yakovenko.
+// 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 "classes.hpp"
+
+namespace bp = boost::python;
+
+namespace boost{ namespace python{
+
+ template<class T>
+ inline T * get_pointer(smart_ptr_t<T> const& p){
+ return p.get();
+ }
+
+ template <class T>
+ struct pointee< smart_ptr_t<T> >{
+ typedef T type;
+ };
+
+} }
+
+
+struct base_wrapper_t : base_i, bp::wrapper< base_i > {
+
+ base_wrapper_t()
+ : base_i(), bp::wrapper< base_i >()
+ {}
+
+ virtual int get_value( ) const {
+ bp::override func_get_value = this->get_override( "get_value" );
+ return func_get_value( );
+ }
+
+};
+
+struct derived_wrapper_t : derived_t, bp::wrapper< derived_t > {
+
+ derived_wrapper_t()
+ : derived_t(), bp::wrapper< derived_t >()
+ {}
+
+ derived_wrapper_t(const derived_t& d)
+ : derived_t(d), bp::wrapper< derived_t >()
+ {}
+
+ derived_wrapper_t(const derived_wrapper_t&)
+ : derived_t(), bp::wrapper< derived_t >()
+ {}
+
+ virtual int get_value() const {
+ if( bp::override func_get_value = this->get_override( "get_value" ) )
+ return func_get_value( );
+ else
+ return derived_t::get_value( );
+ }
+
+ int default_get_value() const {
+ return derived_t::get_value( );
+ }
+
+};
+
+
+BOOST_PYTHON_MODULE( custom_sptr ){
+ bp::class_< base_wrapper_t, boost::noncopyable, smart_ptr_t< base_wrapper_t > >( "base_i" )
+ .def( "get_value", bp::pure_virtual( &base_i::get_value ) );
+
+ bp::implicitly_convertible< smart_ptr_t< base_wrapper_t >, smart_ptr_t< base_i > >();
+
+ bp::class_< derived_wrapper_t, bp::bases< base_i >, smart_ptr_t<derived_wrapper_t> >( "derived_t" )
+ .def( "get_value", &derived_t::get_value, &derived_wrapper_t::default_get_value );
+
+ bp::implicitly_convertible< smart_ptr_t< derived_wrapper_t >, smart_ptr_t< derived_t > >();
+ bp::implicitly_convertible< smart_ptr_t< derived_t >, smart_ptr_t< base_i > >();
+
+ bp::def( "const_ref_get_value", &::const_ref_get_value );
+ bp::def( "ref_get_value", &::ref_get_value );
+ bp::def( "val_get_value", &::val_get_value );
+
+}
Added: pyplusplus_dev/unittests/smart_ptrs/classes.hpp
===================================================================
--- pyplusplus_dev/unittests/smart_ptrs/classes.hpp (rev 0)
+++ pyplusplus_dev/unittests/smart_ptrs/classes.hpp 2006-09-19 20:42:37 UTC (rev 559)
@@ -0,0 +1,41 @@
+#include "smart_ptr.h"
+
+struct base_i{
+public:
+ virtual ~base_i() { }
+ virtual int get_value() const = 0;
+};
+
+
+struct derived_t : base_i{
+ derived_t()
+ {}
+
+ virtual int get_value() const{
+ return 11;
+ }
+};
+
+//Next function could be exposed, but it could not be solved
+//This is the explanation David Abrahams gave:
+//Naturally; there is no instance of smart_ptr_t<base_i> anywhere in the
+//Python object for the reference to bind to. The rules are the same as in C++:
+//
+// int f(smart_ptr_t<base_i>& x) { return 0; }
+// smart_ptr_t<base_wrapper_t> y;
+// int z = f(y); // fails to compile
+
+inline int
+ref_get_value( smart_ptr_t< base_i >& a ){
+ return a->get_value();
+}
+
+inline int
+val_get_value( smart_ptr_t< base_i > a ){
+ return a->get_value();
+}
+
+inline int
+const_ref_get_value( const smart_ptr_t< base_i >& a ){
+ return a->get_value();
+}
Modified: pyplusplus_dev/unittests/smart_ptrs/sconstruct
===================================================================
--- pyplusplus_dev/unittests/smart_ptrs/sconstruct 2006-09-19 20:40:48 UTC (rev 558)
+++ pyplusplus_dev/unittests/smart_ptrs/sconstruct 2006-09-19 20:42:37 UTC (rev 559)
@@ -1,5 +1,5 @@
-SharedLibrary( target=r'cspc_ext'
- , source=[ r'cspc.cpp' ]
+SharedLibrary( target=r'custom_sptr'
+ , source=[ r'bindings.cpp' ]
, LIBS=[ r"boost_python" ]
, LIBPATH=[ r"/home/roman/boost_cvs/bin",r"" ]
, CPPPATH=[ r"/home/roman/boost_cvs",r"/usr/include/python2.4" ]
Added: pyplusplus_dev/unittests/smart_ptrs/smart_ptr.h
===================================================================
--- pyplusplus_dev/unittests/smart_ptrs/smart_ptr.h (rev 0)
+++ pyplusplus_dev/unittests/smart_ptrs/smart_ptr.h 2006-09-19 20:42:37 UTC (rev 559)
@@ -0,0 +1,121 @@
+#ifndef smart_ptr_t_19_09_2006
+#define smart_ptr_t_19_09_2006
+
+#include <assert.h>
+
+template<class T> class smart_ptr_t {
+protected:
+ T* pRep;
+ unsigned int* pUseCount;
+public:
+
+ smart_ptr_t()
+ : pRep(0), pUseCount(0)
+ {}
+
+ //What will happen if rep is NULL? -> bug
+ explicit smart_ptr_t(T* rep)
+ : pRep(rep), pUseCount( new unsigned int(1) )
+ {}
+
+ smart_ptr_t(const smart_ptr_t& r)
+ : pRep(0), pUseCount(0)
+ {
+ pRep = r.get();
+ pUseCount = r.useCountPointer();
+ if(pUseCount){
+ ++(*pUseCount);
+ }
+ }
+
+ smart_ptr_t& operator=(const smart_ptr_t& r){
+ if( pRep == r.pRep ){
+ return *this;
+ }
+
+ release();
+
+ pRep = r.get();
+ pUseCount = r.useCountPointer();
+ if(pUseCount){
+ ++(*pUseCount);
+ }
+ return *this;
+ }
+
+
+ template<class Y>
+ smart_ptr_t(const smart_ptr_t<Y>& r)
+ : pRep(0), pUseCount(0)
+ {
+ pRep = r.get();
+ pUseCount = r.useCountPointer();
+ if(pUseCount){
+ ++(*pUseCount);
+ }
+ }
+
+ template< class Y>
+ smart_ptr_t& operator=(const smart_ptr_t<Y>& r){
+ if( pRep == r.pRep ){
+ return *this;
+ }
+
+ release();
+
+ pRep = r.get();
+ pUseCount = r.useCountPointer();
+ if(pUseCount){
+ ++(*pUseCount);
+ }
+ return *this;
+ }
+
+ virtual ~smart_ptr_t() {
+ release();
+ }
+
+ inline T& operator*() const {
+ assert(pRep); return *pRep;
+ }
+
+ inline T* operator->() const {
+ assert(pRep); return pRep;
+ }
+
+ inline T* get() const {
+ return pRep;
+ }
+
+ inline unsigned int* useCountPointer() const {
+ return pUseCount;
+ }
+
+ inline T* getPointer() const {
+ return pRep;
+ }
+
+protected:
+
+ inline void release(void){
+ bool destroyThis = false;
+
+ if( pUseCount ){
+ if( --(*pUseCount) == 0){
+ destroyThis = true;
+ }
+ }
+ if (destroyThis){
+ destroy();
+ }
+ }
+
+ virtual void destroy(void){
+ delete pRep;
+ delete pUseCount;
+ }
+};
+
+
+#endif //smart_ptr_t_19_09_2006
+
Modified: pyplusplus_dev/unittests/smart_ptrs/test.py
===================================================================
--- pyplusplus_dev/unittests/smart_ptrs/test.py 2006-09-19 20:40:48 UTC (rev 558)
+++ pyplusplus_dev/unittests/smart_ptrs/test.py 2006-09-19 20:42:37 UTC (rev 559)
@@ -1,15 +1,59 @@
-import cspc_ext
+import unittest
+import custom_sptr
-def test_instance( inst ):
- print "call val_get_value( inst ) => %d" % cspc_ext.val_get_value(inst)
- try:
- #this will give us Segmentation fault on Linux
- #But if you comment previuos statement than all will be fine.
- print "call const_ref_get_value( inst ) => %d" % cspc_ext.const_ref_get_value(inst)
- except Exception, error:
- print "\nUnable to call const_ref_get_value( inst ): ", str(error)
+class py_derived_t( custom_sptr.base_i ):
+ def __init__( self ):
+ custom_sptr.base_i.__init__( self )
-print 'testing derived_t instance'
-inst = cspc_ext.derived_t()
-test_instance( inst )
-print 'testing derived_t instance - done'
+ def get_value( self ):
+ return 28
+
+class py_double_derived_t( custom_sptr.derived_t ):
+ def __init__( self ):
+ custom_sptr.derived_t.__init__( self )
+
+ def get_value( self ):
+ return 31
+
+class tester_t( unittest.TestCase ):
+ def __init__( self, *args ):
+ unittest.TestCase.__init__( self, *args )
+
+ def __test_ref( self, inst ):
+ try:
+ custom_sptr.ref_get_value( inst )
+ self.fail( 'ArgumentError was not raised.' )
+ except Exception, error:
+ self.failUnless( error.__class__.__name__ == 'ArgumentError' )
+
+ def __test_val( self, inst, val ):
+ self.assertEqual( custom_sptr.val_get_value( inst ), val )
+
+ def __test_const_ref( self, inst, val ):
+ self.assertEqual( custom_sptr.const_ref_get_value( inst ), val )
+
+ def __test_impl( self, inst, val ):
+ self.__test_ref( inst )
+ self.__test_val( inst, val )
+ self.__test_const_ref( inst, val )
+
+ def test_derived( self ):
+ self.__test_impl( custom_sptr.derived_t(), 11 )
+
+ def test_py_derived( self ):
+ self.__test_impl( py_derived_t(), 28 )
+
+ def test_py_double_derived_t( self ):
+ self.__test_impl( py_double_derived_t(), 31 )
+
+
+def create_suite():
+ suite = unittest.TestSuite()
+ suite.addTest( unittest.makeSuite(tester_t))
+ return suite
+
+def run_suite():
+ unittest.TextTestRunner(verbosity=2).run( create_suite() )
+
+if __name__ == "__main__":
+ run_suite()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|