pygccxml-commit Mailing List for C++ Python language bindings (Page 52)
Brought to you by:
mbaas,
roman_yakovenko
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
(190) |
Apr
(166) |
May
(170) |
Jun
(75) |
Jul
(105) |
Aug
(131) |
Sep
(99) |
Oct
(84) |
Nov
(67) |
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(66) |
Feb
(49) |
Mar
(25) |
Apr
(62) |
May
(21) |
Jun
(34) |
Jul
(9) |
Aug
(21) |
Sep
(5) |
Oct
|
Nov
(63) |
Dec
(34) |
2008 |
Jan
(10) |
Feb
(42) |
Mar
(26) |
Apr
(25) |
May
(6) |
Jun
(40) |
Jul
(18) |
Aug
(29) |
Sep
(6) |
Oct
(32) |
Nov
(14) |
Dec
(56) |
2009 |
Jan
(127) |
Feb
(52) |
Mar
(2) |
Apr
(10) |
May
(29) |
Jun
(3) |
Jul
|
Aug
(16) |
Sep
(4) |
Oct
(11) |
Nov
(8) |
Dec
(14) |
2010 |
Jan
(31) |
Feb
(1) |
Mar
(7) |
Apr
(9) |
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
(8) |
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <mb...@us...> - 2006-09-20 16:54:20
|
Revision: 565 http://svn.sourceforge.net/pygccxml/?rev=565&view=rev Author: mbaas Date: 2006-09-20 09:54:14 -0700 (Wed, 20 Sep 2006) Log Message: ----------- Modified visit_member_function() so that the GIL class gets written and included. Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-20 16:52:11 UTC (rev 564) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-20 16:54:14 UTC (rev 565) @@ -564,6 +564,13 @@ # Set the wrapper so that the registration code will refer to it maker.wrapper = mftw + # Include the gil_state header from the code repository. + if not self.__extmodule.is_system_header(code_repository.gil_state.file_name): + self.__extmodule.add_system_header( code_repository.gil_state.file_name ) + self.__extmodule.adopt_creator( code_creators.include_t( code_repository.gil_state.file_name ) + , self.__extmodule.first_include_index() + 1) + + if self.curr_decl.has_static: #static_method should be created only once. found = filter( lambda creator: isinstance( creator, code_creators.static_method_t ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-20 16:52:15
|
Revision: 564 http://svn.sourceforge.net/pygccxml/?rev=564&view=rev Author: mbaas Date: 2006-09-20 09:52:11 -0700 (Wed, 20 Sep 2006) Log Message: ----------- Modified the thread_safe code. This code can be enabled by setting an attribute thread_safe to True on the decl_wrapper. Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-09-20 16:50:09 UTC (rev 563) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-09-20 16:52:11 UTC (rev 564) @@ -229,6 +229,8 @@ # Stores the name of the variable that holds the override self._override_var = None + # Stores the name of the 'gstate' variable + self._gstate_var = None def default_name(self): """Return the name of the 'default' function. @@ -317,28 +319,31 @@ def create_virtual_body(self): - thread_safe = False + thread_safe = getattr(self.declaration, "thread_safe", False) if thread_safe: - # Todo: Properly allocate "gstate" body = """ -PyGILState_STATE gstate; -gstate = PyGILState_Ensure(); +pyplusplus::gil_state_t %(gstate_var)s; -$DECLARATIONS +%(gstate_var)s.ensure(); +boost::python::override %(override_var)s = this->get_override( "%(alias)s" ); +%(gstate_var)s.release(); -PyGILState_Release(gstate); - if( %(override_var)s ) { - gstate = PyGILState_Ensure(); + // The corresponding release() is done in the destructor of %(gstate_var)s + %(gstate_var)s.ensure(); - try { + $DECLARATIONS + + try { $PRE_CALL ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); $POST_CALL + + $RETURN_STMT } catch(...) { @@ -346,11 +351,11 @@ { PyErr_Print(); } - PyGILState_Release(gstate); - throw; + + $CLEANUP + + $EXCEPTION_HANDLER_EXIT } - PyGILState_Release(gstate); - $RETURN_STMT } else { @@ -360,10 +365,12 @@ if not thread_safe: body = """ -$DECLARATIONS +boost::python::override %(override_var)s = this->get_override( "%(alias)s" ); if( %(override_var)s ) { + $DECLARATIONS + $PRE_CALL ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); @@ -398,6 +405,7 @@ return body % { # 'override' : self.override_identifier() 'override_var' : self._override_var + , 'gstate_var' : self._gstate_var , 'alias' : self.declaration.alias # , 'func_var' : "func_"+self.declaration.alias , 'inherited' : self.create_base_body() @@ -476,7 +484,8 @@ # Create the substitution manager decl = self.declaration sm = function_transformers.substitution_manager_t(decl, transformers=decl.function_transformers) - self._override_var = sm.virtual_func.declare_local(decl.alias+"_callable", "boost::python::override", default='this->get_override( "%s" )'%decl.alias) + self._override_var = sm.virtual_func.allocate_local(decl.alias+"_callable") + self._gstate_var = sm.virtual_func.allocate_local("gstate") self._subst_manager = sm answer = [ self.create_function() ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-20 16:50:16
|
Revision: 563 http://svn.sourceforge.net/pygccxml/?rev=563&view=rev Author: mbaas Date: 2006-09-20 09:50:09 -0700 (Wed, 20 Sep 2006) Log Message: ----------- Added a new header file to the code repository that contains a class to acquire/release the Python GIL. Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_repository/__init__.py Added Paths: ----------- pyplusplus_dev/pyplusplus/code_repository/gil_state.py Modified: pyplusplus_dev/pyplusplus/code_repository/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/__init__.py 2006-09-20 16:46:04 UTC (rev 562) +++ pyplusplus_dev/pyplusplus/code_repository/__init__.py 2006-09-20 16:50:09 UTC (rev 563) @@ -14,4 +14,6 @@ """ import array_1 -all = [ array_1 ] \ No newline at end of file +import gil_state + +all = [ array_1, gil_state ] Added: pyplusplus_dev/pyplusplus/code_repository/gil_state.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/gil_state.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_repository/gil_state.py 2006-09-20 16:50:09 UTC (rev 563) @@ -0,0 +1,62 @@ +# 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) + +""" +This file contains C++ code to acquire/release the GIL. +""" + +file_name = "__gil_state.pypp.hpp" + +code = \ +"""// 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) + +#ifndef __gil_state_pyplusplus_hpp__ +#define __gil_state_pyplusplus_hpp__ + +namespace pyplusplus{ + +class gil_state_t +{ + public: + gil_state_t( bool lock=false ) + : m_locked( false ) + { + if( lock ) + ensure(); + } + + ~gil_state_t() { + release(); + } + + void ensure() { + if( !m_locked ) + { + m_gstate = PyGILState_Ensure(); + m_locked = true; + } + } + + void release() { + if( m_locked ) + { + PyGILState_Release(m_gstate); + m_locked = false; + } + } + + private: + bool m_locked; + PyGILState_STATE m_gstate; +}; + +} /* pyplusplus*/ + + +#endif//__gil_state_pyplusplus_hpp__ +""" Property changes on: pyplusplus_dev/pyplusplus/code_repository/gil_state.py ___________________________________________________________________ Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-20 16:46:09
|
Revision: 562 http://svn.sourceforge.net/pygccxml/?rev=562&view=rev Author: mbaas Date: 2006-09-20 09:46:04 -0700 (Wed, 20 Sep 2006) Log Message: ----------- Added a new method code_manager_t.allocate_local() and two new variables CLEANUP and EXCEPTION_HANDLER_EXIT. Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/function_transformers/code_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-09-20 07:43:39 UTC (rev 561) +++ pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-09-20 16:46:04 UTC (rev 562) @@ -44,6 +44,8 @@ @type result_type: str @ivar result_expr: A string containing the expression that will be put after the "return" statement. This expression is used for the variable RETURN_STMT. @type result_expr: str + @ivar exception_handler_exit: The C++ code that is executed at the end of the main exception handler (default: "throw;"). + @type exception_handler_exit: str @author: Matthias Baas """ @@ -53,7 +55,8 @@ """ subst_t.__init__(self, blockvars=["DECLARATIONS", "PRE_CALL", - "POST_CALL"]) + "POST_CALL", + "EXCEPTION_HANDLER_EXIT"]) # The name of the class of which the generated function is a member # (pass None or an empty string if the function is a free function) @@ -80,6 +83,12 @@ # the "return" statement. self.result_expr = None + # The C++ code that is executed at the end of the main + # exception handler. + self.exception_handler_exit = "throw;" + + # Key:Variable name / Value:1 + self._allocated_vars = {} # Key:Variable name / Value:(type,size,default) self._declared_vars = {} # A list with variable tuples: (name, type, size, default) @@ -100,11 +109,30 @@ @return: The assigned variable name (which is guaranteed to be unique) @rtype: str """ - name = self._make_name_unique(name) + name = self.allocate_local(name) self._declared_vars[name] = (type,size,default) self._local_var_list.append((name, type, size, default)) return name + # allocate_local + def allocate_local(self, name): + """Allocate a local variable name and return the final name. + + Allocate a variable name that is unique to the entire + function. The variable will not appear in the DECLARATIONS + block. Instead, the caller has to generate the declaration + code himself at an appropriate place. + + @param name: The desired variable name + @type name: str + @return: The assigned variable name (which is guaranteed to be unique) + @rtype: str + """ + name = self._make_name_unique(name) + self._allocated_vars[name] = 1 + return name + + # is_defined def is_defined(self, name): """Check if a variable name is already in use. @@ -113,7 +141,7 @@ @rtype: bool """ - if name in self._declared_vars: + if name in self._allocated_vars: return True if filter(lambda a: a.name==name, self.arg_list): return True @@ -127,6 +155,8 @@ @return: Returns the type of the specified local variable. @rtype: str """ + if name in self._allocated_vars: + raise ValueError, 'The type of local variable "%s" is unknown.'%name if name not in self._declared_vars: raise ValueError, 'Local variable "%s" not found.'%name @@ -202,6 +232,12 @@ else: self.RETURN_STMT = "" + # EXCEPTION_HANDLER_EXIT + if self.exception_handler_exit!=None: + self.EXCEPTION_HANDLER_EXIT = self.exception_handler_exit + else: + self.EXCEPTION_HANDLER_EXIT = "" + # _make_name_unique def _make_name_unique(self, name): """Make a variable name unique so that there's no clash with other names. Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-20 07:43:39 UTC (rev 561) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-20 16:46:04 UTC (rev 562) @@ -148,7 +148,11 @@ | [} catch(...) {...}] | +--------------------------+ + - CLEANUP: The cleanup code blocks of all function transformers. + - RETURN_STMT: "return <varname>" or "return boost::python::make_tuple(...)" + + - EXCEPTION_HANDLER_EXIT: The C++ code that is executed at the end of the main exception handler (default: "throw;") @ivar wrapper_func: The L{code manager<code_manager_t>} object that manages the wrapper function. This is used by the arg policies to modify the wrapper function. @@ -297,6 +301,12 @@ postcall = "\n\n".join(src) self.wrapper_func.POST_CALL = postcall + # Create the wrapper function cleanup block... + src = map(lambda cb: getattr(cb, "wrapper_cleanup", defmeth)(self), transformers) + src = filter(lambda x: x!=None, src) + cleanup = "\n\n".join(src) + self.wrapper_func.CLEANUP = cleanup + # Create the virtual function pre-call block... src = map(lambda cb: getattr(cb, "virtual_pre_call", defmeth)(self), transformers) src = filter(lambda x: x!=None, src) @@ -309,8 +319,14 @@ src.reverse() postcall = "\n\n".join(src) self.virtual_func.POST_CALL = postcall - + # Create the virtual function cleanup block... + src = map(lambda cb: getattr(cb, "virtual_cleanup", defmeth)(self), transformers) + src = filter(lambda x: x!=None, src) + cleanup = "\n\n".join(src) + self.virtual_func.CLEANUP = cleanup + + # remove_arg def remove_arg(self, idx): """Remove an argument from the wrapper function. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-20 07:43:47
|
Revision: 561 http://svn.sourceforge.net/pygccxml/?rev=561&view=rev Author: roman_yakovenko Date: 2006-09-20 00:43:39 -0700 (Wed, 20 Sep 2006) Log Message: ----------- adding new use case for smart ptr Modified Paths: -------------- pyplusplus_dev/unittests/smart_ptrs/bindings.cpp pyplusplus_dev/unittests/smart_ptrs/classes.hpp pyplusplus_dev/unittests/smart_ptrs/test.py Modified: pyplusplus_dev/unittests/smart_ptrs/bindings.cpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/bindings.cpp 2006-09-20 06:02:54 UTC (rev 560) +++ pyplusplus_dev/unittests/smart_ptrs/bindings.cpp 2006-09-20 07:43:39 UTC (rev 561) @@ -80,6 +80,7 @@ .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::register_ptr_to_python< 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 ); @@ -87,10 +88,11 @@ 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::implicitly_convertible< derived_ptr_t, smart_ptr_t< derived_t > >(); - boost::python::register_ptr_to_python< derived_ptr_t >(); + bp::register_ptr_to_python< derived_ptr_t >(); 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 ); bp::def( "create_derived", &::create_derived ); + bp::def( "create_base", &::create_base ); } Modified: pyplusplus_dev/unittests/smart_ptrs/classes.hpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/classes.hpp 2006-09-20 06:02:54 UTC (rev 560) +++ pyplusplus_dev/unittests/smart_ptrs/classes.hpp 2006-09-20 07:43:39 UTC (rev 561) @@ -61,6 +61,11 @@ return derived_ptr_t( new derived_t() ); } +smart_ptr_t< base_i > create_base(){ + return smart_ptr_t< base_i >( new derived_t() ); +} + + //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 Modified: pyplusplus_dev/unittests/smart_ptrs/test.py =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/test.py 2006-09-20 06:02:54 UTC (rev 560) +++ pyplusplus_dev/unittests/smart_ptrs/test.py 2006-09-20 07:43:39 UTC (rev 561) @@ -26,6 +26,9 @@ except Exception, error: self.failUnless( error.__class__.__name__ == 'ArgumentError' ) + def __test_ref_fine( self, inst, val ): + self.assertEqual( custom_sptr.ref_get_value( inst ), val ) + def __test_val( self, inst, val ): self.assertEqual( custom_sptr.val_get_value( inst ), val ) @@ -49,6 +52,13 @@ def test_created_derived( self ): self.__test_impl( custom_sptr.create_derived(), 11 ) + def test_created_base( self ): + inst = custom_sptr.create_base() + val = 11 + self.__test_ref_fine( inst, val ) + self.__test_val( inst, val ) + self.__test_const_ref( inst, val ) + def create_suite(): suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-20 06:03:02
|
Revision: 560 http://svn.sourceforge.net/pygccxml/?rev=560&view=rev Author: roman_yakovenko Date: 2006-09-19 23:02:54 -0700 (Tue, 19 Sep 2006) Log Message: ----------- adding new use case for smart ptr Modified Paths: -------------- pyplusplus_dev/unittests/smart_ptrs/bindings.cpp pyplusplus_dev/unittests/smart_ptrs/classes.hpp pyplusplus_dev/unittests/smart_ptrs/test.py Modified: pyplusplus_dev/unittests/smart_ptrs/bindings.cpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/bindings.cpp 2006-09-19 20:42:37 UTC (rev 559) +++ pyplusplus_dev/unittests/smart_ptrs/bindings.cpp 2006-09-20 06:02:54 UTC (rev 560) @@ -22,6 +22,16 @@ typedef T type; }; + + inline derived_t * get_pointer(derived_ptr_t const& p){ + return p.get(); + } + + template<> + struct pointee< derived_ptr_t >{ + typedef derived_t type; + }; + } } @@ -65,7 +75,6 @@ }; - 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 ) ); @@ -77,9 +86,11 @@ 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::implicitly_convertible< derived_ptr_t, smart_ptr_t< derived_t > >(); + boost::python::register_ptr_to_python< derived_ptr_t >(); 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 ); - + bp::def( "create_derived", &::create_derived ); } Modified: pyplusplus_dev/unittests/smart_ptrs/classes.hpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/classes.hpp 2006-09-19 20:42:37 UTC (rev 559) +++ pyplusplus_dev/unittests/smart_ptrs/classes.hpp 2006-09-20 06:02:54 UTC (rev 560) @@ -16,6 +16,51 @@ } }; +struct derived_ptr_t : public smart_ptr_t< derived_t >{ + + derived_ptr_t() + : smart_ptr_t< derived_t >() + {} + + explicit derived_ptr_t(derived_t* rep) + : smart_ptr_t<derived_t>(rep) + {} + + derived_ptr_t(const derived_ptr_t& r) + : smart_ptr_t<derived_t>(r) {} + + derived_ptr_t( const smart_ptr_t< base_i >& r) + : smart_ptr_t<derived_t>() + { + pRep = static_cast<derived_t*>(r.getPointer()); + pUseCount = r.useCountPointer(); + if (pUseCount) + { + ++(*pUseCount); + } + } + + derived_ptr_t& operator=(const smart_ptr_t< base_i >& r) + { + if (pRep == static_cast<derived_t*>(r.getPointer())) + return *this; + release(); + pRep = static_cast<derived_t*>(r.getPointer()); + pUseCount = r.useCountPointer(); + if (pUseCount) + { + ++(*pUseCount); + } + + return *this; + } +}; + + +derived_ptr_t create_derived(){ + return derived_ptr_t( new derived_t() ); +} + //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 Modified: pyplusplus_dev/unittests/smart_ptrs/test.py =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/test.py 2006-09-19 20:42:37 UTC (rev 559) +++ pyplusplus_dev/unittests/smart_ptrs/test.py 2006-09-20 06:02:54 UTC (rev 560) @@ -43,9 +43,11 @@ def test_py_derived( self ): self.__test_impl( py_derived_t(), 28 ) - def test_py_double_derived_t( self ): + def test_py_double_derived( self ): self.__test_impl( py_double_derived_t(), 31 ) + def test_created_derived( self ): + self.__test_impl( custom_sptr.create_derived(), 11 ) def create_suite(): suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-19 20:42:48
|
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. |
From: <rom...@us...> - 2006-09-19 20:40:53
|
Revision: 558 http://svn.sourceforge.net/pygccxml/?rev=558&view=rev Author: roman_yakovenko Date: 2006-09-19 13:40:48 -0700 (Tue, 19 Sep 2006) Log Message: ----------- removing partial files from smart_ptrs example Removed Paths: ------------- pyplusplus_dev/unittests/smart_ptrs/cspc.cpp pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp Deleted: pyplusplus_dev/unittests/smart_ptrs/cspc.cpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/cspc.cpp 2006-09-19 07:48:00 UTC (rev 557) +++ pyplusplus_dev/unittests/smart_ptrs/cspc.cpp 2006-09-19 20:40:48 UTC (rev 558) @@ -1,177 +0,0 @@ -// 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 <assert.h> - -//defining smart pointer class - -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; - } -}; - - -//defining few classes and functions that should be exposed to Python - - -struct derived_t{ - virtual int get_value(void) const{ - return 11; - } -}; - - -int -val_get_value( smart_ptr_t<derived_t> a ){ - return a->get_value(); -} - -int -const_ref_get_value( const smart_ptr_t<derived_t>& a ){ - if( a.get() ){ - return a->get_value(); - } - else{ - return -1; - } -} - -//Expose code - -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; - }; - -} } - -BOOST_PYTHON_MODULE( cspc_ext ){ - - bp::class_< derived_t, smart_ptr_t<derived_t> >( "derived_t" ) - .def( "get_value", &::derived_t::get_value ); - - bp::def( "const_ref_get_value", &::const_ref_get_value ); - bp::def( "val_get_value", &::val_get_value ); - -} Deleted: pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp 2006-09-19 07:48:00 UTC (rev 557) +++ pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp 2006-09-19 20:40:48 UTC (rev 558) @@ -1,161 +0,0 @@ -// 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" - -#include "iostream" - -# include <boost/python/converter/from_python.hpp> -# include <boost/python/converter/rvalue_from_python_data.hpp> -# include <boost/python/converter/registered.hpp> - -namespace bp = boost::python; -namespace bpc = boost::python::converter; - -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; - }; - -} } - -template <typename T> -struct smart_ptr_to_python{ - - static PyObject * - convert(smart_ptr_t<T> const& s_ptr){ - if( !s_ptr.get() ){ - return bp::detail::none(); - } - else{ - return bpc::registered< smart_ptr_t<T> const&>::converters.to_python(&s_ptr); - } - } - -}; - -template <class SmartPtrInst> -struct smart_ptr_from_python { - - typedef typename boost::python::pointee<SmartPtrInst>::type Pointee; - - smart_ptr_from_python() { - bpc::registry::insert( &convertible, &construct, bp::type_id<SmartPtrInst>() ); - } - -private: - - static void* convertible(PyObject *p) { - // can always produce a pointer from None. - if (p == Py_None) - return p; - // Otherwise, we can do it if we can get the pointee out. - void *result = bpc::get_lvalue_from_python(p, bpc::registered<Pointee>::converters); - return result; - } - - static void construct(PyObject* source, bpc::rvalue_from_python_stage1_data* data){ - void* const storage = ((bpc::rvalue_from_python_storage<SmartPtrInst>*)data)->storage.bytes; - // Deal with the "None" case. - if (data->convertible == source) - new (storage) SmartPtrInst(); // Or whatever you want. - else - new (storage)SmartPtrInst(static_cast<Pointee*>(data->convertible)); - data->convertible = storage; - } -}; - - -struct base_i_wrapper : base_i, bp::wrapper< base_i > { - - base_i_wrapper() - : base_i() - , bp::wrapper< base_i >(){ - // null constructor - - } - - 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 const & arg ) - : derived_t( arg ) - , bp::wrapper< derived_t >(){ - // copy constructor - - } - - derived_wrapper_t(int value ) - : derived_t( value ) - , bp::wrapper< derived_t >() - { // Normal constructor - - } - - virtual int get_add_value( ) const { - if( bp::override func_get_add_value = this->get_override( "get_add_value" ) ) - return func_get_add_value( ); - else - return derived_t::get_add_value( ); - } - - - int default_get_add_value( ) const { - return derived_t::get_add_value( ); - } - - 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_i_wrapper, boost::noncopyable >( "base_i" ) - .def( "get_value", bp::pure_virtual( &::base_i::get_value ) ); - - bp::class_< derived_wrapper_t, bp::bases< base_i >, smart_ptr_t<derived_t> >( "derived_t", bp::init< int >(( bp::arg("value") )) ) - .def( "get_add_value", &::derived_t::get_add_value, &derived_wrapper_t::default_get_add_value ) - .def( "get_value", &::derived_t::get_value, &derived_wrapper_t::default_get_value ); - - 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 ); - - smart_ptr_from_python< smart_ptr_t< base_i> >(); - bp::to_python_converter< smart_ptr_t<base_i>, smart_ptr_to_python< base_i > >(); - - smart_ptr_from_python< smart_ptr_t< derived_t> >(); - bp::to_python_converter< smart_ptr_t<derived_t>, smart_ptr_to_python< derived_t > >(); - - bp::implicitly_convertible< smart_ptr_t< derived_t >, smart_ptr_t< base_i > >(); - -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-19 07:48:08
|
Revision: 557 http://svn.sourceforge.net/pygccxml/?rev=557&view=rev Author: mbaas Date: 2006-09-19 00:48:00 -0700 (Tue, 19 Sep 2006) Log Message: ----------- Switched to using the string.Template class for doing substitutions. This slightly modified semantics: Undefined variables are no longer treated as being empty but won't get substituted at all. Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py pyplusplus_dev/pyplusplus/function_transformers/subst.py Modified: pyplusplus_dev/pyplusplus/function_transformers/code_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-09-18 21:45:16 UTC (rev 556) +++ pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-09-19 07:48:00 UTC (rev 557) @@ -184,10 +184,14 @@ # RESULT_VAR_ASSIGNMENT if self.result_var!=None: self.RESULT_VAR_ASSIGNMENT = "%s = "%self.result_var + else: + self.RESULT_VAR_ASSIGNMENT = "" # RESULT_TYPE if self.result_type!=None: self.RESULT_TYPE = str(self.result_type) + else: + self.RESULT_TYPE = "" # INPUT_PARAMS self.INPUT_PARAMS = ", ".join(self.input_params) @@ -195,6 +199,8 @@ # RETURN_STMT if self.result_expr!=None: self.RETURN_STMT = "return %s;"%self.result_expr + else: + self.RETURN_STMT = "" # _make_name_unique def _make_name_unique(self, name): Modified: pyplusplus_dev/pyplusplus/function_transformers/subst.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/subst.py 2006-09-18 21:45:16 UTC (rev 556) +++ pyplusplus_dev/pyplusplus/function_transformers/subst.py 2006-09-19 07:48:00 UTC (rev 557) @@ -9,6 +9,7 @@ """ import re +import string # subst_t class subst_t: @@ -16,9 +17,9 @@ This class performs text substitutions on a template string. The variables are simply stored as attributes inside the class and may - be of any type that can be converted to a string. An empty string - is used if a template string references a variable that does not - exist. + be of any type that can be converted to a string. + If a template string references a variable that does not exist, + the reference is not substituted. Example:: @@ -76,11 +77,11 @@ def substitute(self, template): """Substitute the variables in template and return the result. - All variables of the form "$<varname>" are replaced with the - corresponding attribute <varname>. Block variables must appear - in one single line. The indendation of the variable determines - the indendation of the entire block. - Unknown variables will be substituted with an empty string. + All variables of the form "$<varname>" or "${varname}" are + replaced with the corresponding attribute <varname>. Block + variables must appear in one single line. The indendation of + the variable determines the indendation of the entire block. + References to unknown variables won't get substituted. @param template: The template string @type template: str @@ -108,17 +109,8 @@ code = "\n".join(lines) # Replace the non-block variables... - varexpr = re.compile("\$[a-zA-Z_]+|\$\{[a-zA-Z_]+\}") - while 1: - m = varexpr.search(code) - if m==None: - break - s = m.start() - e = m.end() - key = code[s+1:e] - if key[0]=="{": - key = key[1:-1] - code = "%s%s%s"%(code[:s], getattr(self, key, ""), code[e:]) + tmpl = string.Template(code) + code = tmpl.safe_substitute(self.__dict__) # Replace trailing blanks on each line... expr = re.compile("[ ]+$", re.MULTILINE) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 21:45:21
|
Revision: 556 http://svn.sourceforge.net/pygccxml/?rev=556&view=rev Author: roman_yakovenko Date: 2006-09-18 14:45:16 -0700 (Mon, 18 Sep 2006) Log Message: ----------- update smart ptr Modified Paths: -------------- pyplusplus_dev/unittests/smart_ptrs/cspc.cpp Modified: pyplusplus_dev/unittests/smart_ptrs/cspc.cpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/cspc.cpp 2006-09-18 20:42:11 UTC (rev 555) +++ pyplusplus_dev/unittests/smart_ptrs/cspc.cpp 2006-09-18 21:45:16 UTC (rev 556) @@ -25,6 +25,31 @@ : 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) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 20:42:22
|
Revision: 555 http://svn.sourceforge.net/pygccxml/?rev=555&view=rev Author: roman_yakovenko Date: 2006-09-18 13:42:11 -0700 (Mon, 18 Sep 2006) Log Message: ----------- introducing opaque_type_registrator This is a start for next "redesign" session. New base class for code creators should be introduced: regstration_t. It will keep the list of associated creators, that register declarations in global scope Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-09-18 20:03:06 UTC (rev 554) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-09-18 20:42:11 UTC (rev 555) @@ -30,6 +30,12 @@ def __init__(self, function, wrapper=None ): declaration_based.declaration_based_t.__init__( self, declaration=function ) self._wrapper = wrapper + self._associated_decl_creators = [] + + @property + def associated_decl_creators( self ): + """ references to declaration code creators. """ + return self._associated_decl_creators def _get_wrapper( self ): return self._wrapper Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-09-18 20:03:06 UTC (rev 554) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-09-18 20:42:11 UTC (rev 555) @@ -99,18 +99,6 @@ """ references to class declaration code creators. """ return self._associated_decl_creators - def recursive_associated_decl_creators( self ): - """ references to all class declaration code creators. """ - associated_creators = self.associated_decl_creators[:] - - relevant_creators = filter( lambda creator: isinstance( creator, class_t ) - , algorithm.make_flatten( self.creators ) ) - - map( lambda creator: associated_creators.extend( creator.associated_decl_creators ) - , relevant_creators ) - - return associated_creators - def _get_held_type(self): return self.declaration.held_type def _set_held_type(self, held_type): Modified: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-09-18 20:03:06 UTC (rev 554) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-09-18 20:42:11 UTC (rev 555) @@ -183,10 +183,11 @@ creators = filter( lambda x: isinstance(x, class_types ), class_creator.creators ) decl_creators = [] - for creator in creators: - if not isinstance( creator, code_creators.class_t ): - continue - decl_creators.extend( creator.recursive_associated_decl_creators() ) + class_creators = filter( lambda creator: isinstance( creator, code_creators.class_t ) + , creators ) + + map( lambda creator: decl_creators.extend( self.associated_decl_creators( creator ) ) + , class_creators ) self.split_internal_creators( class_creator, creators, 'classes', decl_creators ) return 'classes' Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-18 20:03:06 UTC (rev 554) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-18 20:42:11 UTC (rev 555) @@ -61,6 +61,21 @@ @type: str """ ) + def associated_decl_creators( self, creator ): + """ references to all class declaration code creators. """ + if not isinstance( creator, code_creators.class_t ): + return [] + + associated_creators = creator.associated_decl_creators[:] + + relevant_creators = filter( lambda acreator: isinstance( acreator, code_creators.class_t ) + , code_creators.make_flatten( creator.creators ) ) + + map( lambda acreator: associated_creators.extend( acreator.associated_decl_creators ) + , relevant_creators ) + + return associated_creators + def create_function_code( self, function_name ): return "void %s();" % function_name @@ -199,7 +214,7 @@ class_wrapper = None decl_creators = [] if isinstance( class_creator, code_creators.class_t ): - decl_creators.extend( class_creator.recursive_associated_decl_creators() ) + decl_creators.extend( self.associated_decl_creators( class_creator ) ) if class_creator.wrapper: class_wrapper = class_creator.wrapper decl_creators.append( class_creator.wrapper ) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-18 20:03:06 UTC (rev 554) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-18 20:42:11 UTC (rev 555) @@ -131,7 +131,8 @@ self.__array_1_registered = set() #(type.decl_string,size) self.__free_operators = [] self.__exposed_free_fun_overloads = set() - + self.__exposed_opaque_decls = set() + def _prepare_decls( self, decls, doc_extractor ): global DO_NOT_REPORT_MSGS @@ -316,6 +317,18 @@ return True #we already decided that those functions should be exposed, so I need wrapper for them return bool( self.redefined_funcs(class_inst) ) + def register_opaque_type( self, type_, call_policy ): + if not decl_wrappers.is_return_opaque_pointer_policy( call_policy ): + return #not our case + naked_type = declarations.remove_cv( declarations.remove_pointer( type_ ) ) + if decl_wrappers.python_traits.is_immutable( naked_type ): + return #don't register opaque converter for immutable types. + if decl in self.__exposed_opaque_decls: + return #already registered + self.__exposed_opaque_decls.add( decl ) + creator = code_creators.opaque_type_registrator_t( decl ) + self.__extmodule.adopt_declaration_creator( creator ) + def _adopt_free_operator( self, operator ): def adopt_operator_impl( operator, found_creators ): creator = filter( lambda creator: isinstance( creator, code_creators.class_t ) @@ -520,7 +533,8 @@ self.__types_db.update( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) - + self.register_opaque_type( self.curr_decl.return_type, self.curr_decl.call_policies ) + maker_cls, fwrapper_cls = creators_wizard.find_out_mem_fun_creator_classes( self.curr_decl ) maker = None @@ -598,7 +612,8 @@ if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) - + self.register_opaque_type( self.curr_decl.return_type, self.curr_decl.call_policies ) + self.__types_db.update( self.curr_decl ) if not self.curr_decl.parent.is_abstract \ and not declarations.is_reference( self.curr_decl.return_type ): @@ -627,7 +642,7 @@ self.__types_db.update( f ) if None is f.call_policies: f.call_policies = self.__call_policies_resolver( f ) - + self.register_opaque_type( f.return_type, f.call_policies ) overloads_cls_creator = code_creators.free_fun_overloads_class_t( overloads ) self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) @@ -637,6 +652,7 @@ self.__types_db.update( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) + self.register_opaque_type( self.curr_decl.return_type, self.curr_decl.call_policies ) maker = code_creators.free_function_t( function=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) @@ -664,6 +680,7 @@ self.__types_db.update( f ) if None is f.call_policies: f.call_policies = self.__call_policies_resolver( f ) + self.register_opaque_type( f.return_type, f.call_policies ) overloads_cls_creator = code_creators.mem_fun_overloads_class_t( overloads ) self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) @@ -801,6 +818,7 @@ elif declarations.is_reference( self.curr_decl.type ): if None is self.curr_decl.getter_call_policies: self.curr_decl.getter_call_policies = self.__call_policies_resolver( self.curr_decl, 'get' ) + self.register_opaque_type( self.curr_decl.type, self.curr_decl.getter_call_policies ) if None is self.curr_decl.setter_call_policies: self.curr_decl.setter_call_policies = self.__call_policies_resolver( self.curr_decl, 'set' ) wrapper = code_creators.mem_var_ref_wrapper_t( variable=self.curr_decl ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 20:03:17
|
Revision: 554 http://svn.sourceforge.net/pygccxml/?rev=554&view=rev Author: roman_yakovenko Date: 2006-09-18 13:03:06 -0700 (Mon, 18 Sep 2006) Log Message: ----------- adding opaque type registrator Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py Added Paths: ----------- pyplusplus_dev/pyplusplus/code_creators/opaque_type_registrator.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-18 20:01:34 UTC (rev 553) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-18 20:03:06 UTC (rev 554) @@ -120,3 +120,5 @@ from exception_translator import exception_translator_t from exception_translator import exception_translator_register_t + +from opaque_type_registrator import opaque_type_registrator_t \ No newline at end of file Added: pyplusplus_dev/pyplusplus/code_creators/opaque_type_registrator.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/opaque_type_registrator.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/opaque_type_registrator.py 2006-09-18 20:03:06 UTC (rev 554) @@ -0,0 +1,19 @@ +# 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) + +import os +import declaration_based + +class opaque_type_registrator_t( declaration_based.declaration_based_t ): + """ + This class creates code that register static sized array + """ + def __init__( self, pointee ): + declaration_based.declaration_based_t.__init__( self, pointee ) + self.works_on_instance = False + + def _create_impl(self): + return 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID( %s )' % self.decl_identifier + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 20:01:45
|
Revision: 553 http://svn.sourceforge.net/pygccxml/?rev=553&view=rev Author: roman_yakovenko Date: 2006-09-18 13:01:34 -0700 (Mon, 18 Sep 2006) Log Message: ----------- adding small convinience function Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-09-18 20:00:50 UTC (rev 552) +++ pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-09-18 20:01:34 UTC (rev 553) @@ -80,6 +80,7 @@ from call_policies import return_by_value from call_policies import return_opaque_pointer from call_policies import return_value_policy +from call_policies import is_return_opaque_pointer_policy from decl_wrapper_printer import decl_wrapper_printer_t from decl_wrapper_printer import print_declarations This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 20:00:55
|
Revision: 552 http://svn.sourceforge.net/pygccxml/?rev=552&view=rev Author: roman_yakovenko Date: 2006-09-18 13:00:50 -0700 (Mon, 18 Sep 2006) Log Message: ----------- adding small convinience function Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py 2006-09-18 19:57:05 UTC (rev 551) +++ pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py 2006-09-18 20:00:50 UTC (rev 552) @@ -217,3 +217,9 @@ def return_value_policy( result_converter_generator, base=None): return return_value_policy_t( result_converter_generator, base ) + + +def is_return_opaque_pointer_policy( policy ): + """returns True is policy represents return_value_policy<return_opaque_pointer>, False otherwise""" + return isinstance( policy, return_value_policy_t ) \ + and policy.result_converter_generator == return_opaque_pointer This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 19:57:23
|
Revision: 551 http://svn.sourceforge.net/pygccxml/?rev=551&view=rev Author: roman_yakovenko Date: 2006-09-18 12:57:05 -0700 (Mon, 18 Sep 2006) Log Message: ----------- adding implicitly_convertible and smart_ptr tests Modified Paths: -------------- pyplusplus_dev/unittests/casting_tester.py pyplusplus_dev/unittests/custom_smart_ptr_classes_tester.py pyplusplus_dev/unittests/data/casting_to_be_exported.hpp pyplusplus_dev/unittests/data/custom_smart_ptr_classes_to_be_exported.hpp Added Paths: ----------- pyplusplus_dev/unittests/impl_conv/ pyplusplus_dev/unittests/impl_conv/ic.cpp pyplusplus_dev/unittests/impl_conv/sconstruct pyplusplus_dev/unittests/impl_conv/test.py pyplusplus_dev/unittests/smart_ptrs/ pyplusplus_dev/unittests/smart_ptrs/cspc.cpp pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp pyplusplus_dev/unittests/smart_ptrs/sconstruct pyplusplus_dev/unittests/smart_ptrs/test.py Modified: pyplusplus_dev/unittests/casting_tester.py =================================================================== --- pyplusplus_dev/unittests/casting_tester.py 2006-09-18 13:41:16 UTC (rev 550) +++ pyplusplus_dev/unittests/casting_tester.py 2006-09-18 19:57:05 UTC (rev 551) @@ -16,6 +16,8 @@ self , tester_t.EXTENSION_NAME , *args ) + def customize( self, mb ): + mb.class_("float_vector").add_registration_code("def( bp::init< const casting::float_vector& >() )") def run_tests( self, module): x_inst = module.x() @@ -24,6 +26,11 @@ self.failUnless( 25 == module.x_value(25) ) self.failUnless( 1 == module.x_value(True) ) self.failUnless( 0 == module.x_value(False) ) + try: + fv = module.float_vector( 5.0 ) + self.fail( "TypeError exception was not raised" ) + except TypeError: + pass def create_suite(): suite = unittest.TestSuite() Modified: pyplusplus_dev/unittests/custom_smart_ptr_classes_tester.py =================================================================== --- pyplusplus_dev/unittests/custom_smart_ptr_classes_tester.py 2006-09-18 13:41:16 UTC (rev 550) +++ pyplusplus_dev/unittests/custom_smart_ptr_classes_tester.py 2006-09-18 19:57:05 UTC (rev 551) @@ -11,10 +11,14 @@ MODULE_SPTR_DECL_CODE = \ """ +# include <boost/python/converter/from_python.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/registered.hpp> + namespace boost{ namespace python{ using namespace controllers; - + using namespace converter; controller_i* get_pointer( my_smart_ptr_t< controller_i > const& p ){ return p.get(); } @@ -35,14 +39,68 @@ }; +template <class T> +struct my_smart_ptr_from_python +{ + my_smart_ptr_from_python() + { + converter::registry::insert(&convertible, &construct, type_id<my_smart_ptr_t<T> >()); + } + + private: + static void* convertible(PyObject* p) + { + if (p == Py_None) + return p; + + return converter::get_lvalue_from_python(p, registered<T>::converters); + } + + static void construct(PyObject* source, rvalue_from_python_stage1_data* data) + { + void* const storage = ((converter::rvalue_from_python_storage<my_smart_ptr_t<T> >*)data)->storage.bytes; + // Deal with the "None" case. + if (data->convertible == source) + new (storage) my_smart_ptr_t<T>(); + else{ + std::cout << "before new (storage) my_smart_ptr_t<T>( static_cast< T* >(data->convertible) );" << std::endl; + new (storage) my_smart_ptr_t<T>( static_cast< T* >(data->convertible) ); + } + data->convertible = storage; + } +}; + + template <class T> + struct ptr_to_python { + static PyObject *convert(my_smart_ptr_t<T> const &p) { + return incref(object(my_smart_ptr_t<T>(p)).ptr()); + } + }; + + //Then you need to do this for each class you register: + //to_python_converter<ptr<T>, ptr_to_python<T> >(); + //You could automate this in a custom def visitor: + + struct smart_ptr_stuff : def_visitor<smart_ptr_stuff> { + friend class def_visitor_access; + template <typename Class> + void visit(Class &c) const { + typedef typename Class::wrapped_type T; + to_python_converter<my_smart_ptr_t<T>, ptr_to_python<T> >(); + } + }; + + }}// namespace boost::python converter """ MODULE_SPTR_REG_CODE = \ """ + boost::python::my_smart_ptr_from_python<controllers::add_x_t>(); + bp::register_ptr_to_python< my_smart_ptr_t< controllers::controller_i > >(); - bp::register_ptr_to_python< my_smart_ptr_t< controllers::add_x_t > >(); + //bp::register_ptr_to_python< my_smart_ptr_t< controllers::add_x_t > >(); bp::implicitly_convertible< my_smart_ptr_t< controllers::add_x_t >, my_smart_ptr_t< controllers::controller_i > >(); @@ -61,7 +119,14 @@ mb.classes( lambda cls: 'ptr' in cls.name).exclude() mb.add_declaration_code( MODULE_SPTR_DECL_CODE ) mb.add_registration_code( MODULE_SPTR_REG_CODE ) + add_x_t = mb.class_( 'add_x_t' ) + add_x_t.held_type = 'my_smart_ptr_t< controllers::add_x_t >' + add_x_t.add_registration_code( 'def(boost::python::smart_ptr_stuff())' ) + mb.build_code_creator( self.EXTENSION_NAME ) + mb.code_creator.add_include( 'iostream' ) + + def create_identity_value( self, module, v ): class identity_value_t( module.value_i ): def __init__( self, v ): @@ -85,10 +150,14 @@ def run_tests(self, module): add_0 = module.add_x_t( 23 ) + print '>',1 self.failUnless( 23 == add_0.get_value() ) - self.failUnless( 23 == module.ref_get_value( add_0 ) ) + print '>',2 self.failUnless( 23 == module.val_get_value( add_0 ) ) + print '>',3 self.failUnless( 23 == module.const_ref_get_value( add_0 ) ) + print '>',4 + self.failUnless( 23 == module.ref_get_value( add_0 ) ) def create_suite(): Modified: pyplusplus_dev/unittests/data/casting_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/casting_to_be_exported.hpp 2006-09-18 13:41:16 UTC (rev 550) +++ pyplusplus_dev/unittests/data/casting_to_be_exported.hpp 2006-09-18 19:57:05 UTC (rev 551) @@ -1,40 +1,57 @@ -// 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) - -#ifndef __casting_to_be_exported_hpp__ -#define __casting_to_be_exported_hpp__ - -namespace casting{ - -struct y{}; - -struct x{ - x() - : value(0) - {} - - explicit x( int i ) - : value( i ) - {} - - x( bool b ) - : value( b ) - {} - - operator int() const { return value; } - - operator y(){ return y(); } - - int value; -}; - - -int identity( int z ){ return z; } - -int x_value(const x& d ){ return d.value; } - -} - -#endif//__casting_to_be_exported_hpp__ +// 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) + +#ifndef __casting_to_be_exported_hpp__ +#define __casting_to_be_exported_hpp__ + +namespace casting{ + +struct y{}; + +struct x{ + x() + : value(0) + {} + + explicit x( int i ) + : value( i ) + {} + + x( bool b ) + : value( b ) + {} + + operator int() const { return value; } + + operator y(){ return y(); } + + int value; +}; + + +int identity( int z ){ return z; } + +int x_value(const x& d ){ return d.value; } + + +struct vector{ + vector(){} + vector( double ){} + vector( const vector& ){} +}; + +struct float_vector{ + float_vector(){} + float_vector( const float_vector& ){} + float_vector( const vector& ){} + float_vector( float ){} +}; + +inline void do_nothing(){ + float_vector( 5.0 ); +} +} + +#endif//__casting_to_be_exported_hpp__ \ No newline at end of file Modified: pyplusplus_dev/unittests/data/custom_smart_ptr_classes_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/custom_smart_ptr_classes_to_be_exported.hpp 2006-09-18 13:41:16 UTC (rev 550) +++ pyplusplus_dev/unittests/data/custom_smart_ptr_classes_to_be_exported.hpp 2006-09-18 19:57:05 UTC (rev 551) @@ -100,6 +100,12 @@ return a->get_value(); } +//inline int +//val_get_value( my_smart_ptr_t< controllers::add_x_t > a ){ +// return a->get_value(); +//} + + inline int val_get_value( controllers::controller_ptr_i a ){ return a->get_value(); Added: pyplusplus_dev/unittests/impl_conv/ic.cpp =================================================================== --- pyplusplus_dev/unittests/impl_conv/ic.cpp (rev 0) +++ pyplusplus_dev/unittests/impl_conv/ic.cpp 2006-09-18 19:57:05 UTC (rev 551) @@ -0,0 +1,36 @@ +#include "boost/python.hpp" + +struct vector{ + vector(){} + vector( double ){} + vector( const vector& ){} +}; + +struct float_vector{ + float_vector(){} + float_vector( const float_vector& ){} + float_vector( const vector& ){} + float_vector( float ){} +}; + +namespace bp = boost::python; + +BOOST_PYTHON_MODULE( ic_ext ){ + + bp::class_< float_vector >( "float_vector" ) + .def( bp::init< >() ) + .def( bp::init< vector const & >() ) + .def( bp::init< float >() ) + .def( bp::init< const float_vector& >() ); + + bp::implicitly_convertible< vector const &, float_vector >(); + + bp::implicitly_convertible< float, float_vector >(); + + bp::class_< vector >( "vector" ) + .def( bp::init< >() ) + .def( bp::init< double >() ); + + bp::implicitly_convertible< double, vector >(); + +} Added: pyplusplus_dev/unittests/impl_conv/sconstruct =================================================================== --- pyplusplus_dev/unittests/impl_conv/sconstruct (rev 0) +++ pyplusplus_dev/unittests/impl_conv/sconstruct 2006-09-18 19:57:05 UTC (rev 551) @@ -0,0 +1,9 @@ +SharedLibrary( target=r'ic_ext' + , source=[ r'ic.cpp' ] + , LIBS=[ r"boost_python" ] + , LIBPATH=[ r"/home/roman/boost_cvs/bin",r"" ] + , CPPPATH=[ r"/home/roman/boost_cvs",r"/usr/include/python2.4" ] + , CCFLAGS=[ '-DBOOST_PYTHON_TRACE_REGISTRY' ] + , SHLIBPREFIX='' + , SHLIBSUFFIX='.so' +) Added: pyplusplus_dev/unittests/impl_conv/test.py =================================================================== --- pyplusplus_dev/unittests/impl_conv/test.py (rev 0) +++ pyplusplus_dev/unittests/impl_conv/test.py 2006-09-18 19:57:05 UTC (rev 551) @@ -0,0 +1,3 @@ +import ic_ext + +ic_ext.float_vector( 5.0 ) Added: pyplusplus_dev/unittests/smart_ptrs/cspc.cpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/cspc.cpp (rev 0) +++ pyplusplus_dev/unittests/smart_ptrs/cspc.cpp 2006-09-18 19:57:05 UTC (rev 551) @@ -0,0 +1,152 @@ +// 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 <assert.h> + +//defining smart pointer class + +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) ) + {} + + 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; + } +}; + + +//defining few classes and functions that should be exposed to Python + + +struct derived_t{ + virtual int get_value(void) const{ + return 11; + } +}; + + +int +val_get_value( smart_ptr_t<derived_t> a ){ + return a->get_value(); +} + +int +const_ref_get_value( const smart_ptr_t<derived_t>& a ){ + if( a.get() ){ + return a->get_value(); + } + else{ + return -1; + } +} + +//Expose code + +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; + }; + +} } + +BOOST_PYTHON_MODULE( cspc_ext ){ + + bp::class_< derived_t, smart_ptr_t<derived_t> >( "derived_t" ) + .def( "get_value", &::derived_t::get_value ); + + bp::def( "const_ref_get_value", &::const_ref_get_value ); + bp::def( "val_get_value", &::val_get_value ); + +} Added: pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp (rev 0) +++ pyplusplus_dev/unittests/smart_ptrs/expose_classes_rvalue.cpp 2006-09-18 19:57:05 UTC (rev 551) @@ -0,0 +1,161 @@ +// 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" + +#include "iostream" + +# include <boost/python/converter/from_python.hpp> +# include <boost/python/converter/rvalue_from_python_data.hpp> +# include <boost/python/converter/registered.hpp> + +namespace bp = boost::python; +namespace bpc = boost::python::converter; + +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; + }; + +} } + +template <typename T> +struct smart_ptr_to_python{ + + static PyObject * + convert(smart_ptr_t<T> const& s_ptr){ + if( !s_ptr.get() ){ + return bp::detail::none(); + } + else{ + return bpc::registered< smart_ptr_t<T> const&>::converters.to_python(&s_ptr); + } + } + +}; + +template <class SmartPtrInst> +struct smart_ptr_from_python { + + typedef typename boost::python::pointee<SmartPtrInst>::type Pointee; + + smart_ptr_from_python() { + bpc::registry::insert( &convertible, &construct, bp::type_id<SmartPtrInst>() ); + } + +private: + + static void* convertible(PyObject *p) { + // can always produce a pointer from None. + if (p == Py_None) + return p; + // Otherwise, we can do it if we can get the pointee out. + void *result = bpc::get_lvalue_from_python(p, bpc::registered<Pointee>::converters); + return result; + } + + static void construct(PyObject* source, bpc::rvalue_from_python_stage1_data* data){ + void* const storage = ((bpc::rvalue_from_python_storage<SmartPtrInst>*)data)->storage.bytes; + // Deal with the "None" case. + if (data->convertible == source) + new (storage) SmartPtrInst(); // Or whatever you want. + else + new (storage)SmartPtrInst(static_cast<Pointee*>(data->convertible)); + data->convertible = storage; + } +}; + + +struct base_i_wrapper : base_i, bp::wrapper< base_i > { + + base_i_wrapper() + : base_i() + , bp::wrapper< base_i >(){ + // null constructor + + } + + 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 const & arg ) + : derived_t( arg ) + , bp::wrapper< derived_t >(){ + // copy constructor + + } + + derived_wrapper_t(int value ) + : derived_t( value ) + , bp::wrapper< derived_t >() + { // Normal constructor + + } + + virtual int get_add_value( ) const { + if( bp::override func_get_add_value = this->get_override( "get_add_value" ) ) + return func_get_add_value( ); + else + return derived_t::get_add_value( ); + } + + + int default_get_add_value( ) const { + return derived_t::get_add_value( ); + } + + 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_i_wrapper, boost::noncopyable >( "base_i" ) + .def( "get_value", bp::pure_virtual( &::base_i::get_value ) ); + + bp::class_< derived_wrapper_t, bp::bases< base_i >, smart_ptr_t<derived_t> >( "derived_t", bp::init< int >(( bp::arg("value") )) ) + .def( "get_add_value", &::derived_t::get_add_value, &derived_wrapper_t::default_get_add_value ) + .def( "get_value", &::derived_t::get_value, &derived_wrapper_t::default_get_value ); + + 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 ); + + smart_ptr_from_python< smart_ptr_t< base_i> >(); + bp::to_python_converter< smart_ptr_t<base_i>, smart_ptr_to_python< base_i > >(); + + smart_ptr_from_python< smart_ptr_t< derived_t> >(); + bp::to_python_converter< smart_ptr_t<derived_t>, smart_ptr_to_python< derived_t > >(); + + bp::implicitly_convertible< smart_ptr_t< derived_t >, smart_ptr_t< base_i > >(); + +} Added: pyplusplus_dev/unittests/smart_ptrs/sconstruct =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/sconstruct (rev 0) +++ pyplusplus_dev/unittests/smart_ptrs/sconstruct 2006-09-18 19:57:05 UTC (rev 551) @@ -0,0 +1,9 @@ +SharedLibrary( target=r'cspc_ext' + , source=[ r'cspc.cpp' ] + , LIBS=[ r"boost_python" ] + , LIBPATH=[ r"/home/roman/boost_cvs/bin",r"" ] + , CPPPATH=[ r"/home/roman/boost_cvs",r"/usr/include/python2.4" ] + , CCFLAGS=[ '-DBOOST_PYTHON_TRACE_REGISTRY' ] + , SHLIBPREFIX='' + , SHLIBSUFFIX='.so' +) Added: pyplusplus_dev/unittests/smart_ptrs/test.py =================================================================== --- pyplusplus_dev/unittests/smart_ptrs/test.py (rev 0) +++ pyplusplus_dev/unittests/smart_ptrs/test.py 2006-09-18 19:57:05 UTC (rev 551) @@ -0,0 +1,15 @@ +import cspc_ext + +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) + +print 'testing derived_t instance' +inst = cspc_ext.derived_t() +test_instance( inst ) +print 'testing derived_t instance - done' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-18 14:00:57
|
Revision: 550 http://svn.sourceforge.net/pygccxml/?rev=550&view=rev Author: mbaas Date: 2006-09-18 06:41:16 -0700 (Mon, 18 Sep 2006) Log Message: ----------- Added the verbose switch so that epydoc displays markup errors when generating the reference manual for pypp_api. Modified Paths: -------------- pyplusplus_dev/contrib/pypp_api/generate_docs.py Modified: pyplusplus_dev/contrib/pypp_api/generate_docs.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/generate_docs.py 2006-09-18 09:10:13 UTC (rev 549) +++ pyplusplus_dev/contrib/pypp_api/generate_docs.py 2006-09-18 13:41:16 UTC (rev 550) @@ -5,7 +5,7 @@ default_format = "epytext" -cmd_line = "epydoc -o html --docformat %s pypp_api"%(default_format) +cmd_line = "epydoc -o html -v --docformat %s pypp_api"%(default_format) print "Running: ", cmd_line os.system(cmd_line) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 09:10:18
|
Revision: 549 http://svn.sourceforge.net/pygccxml/?rev=549&view=rev Author: roman_yakovenko Date: 2006-09-18 02:10:13 -0700 (Mon, 18 Sep 2006) Log Message: ----------- adding set size property for array type Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/cpptypes.py Modified: pygccxml_dev/pygccxml/declarations/cpptypes.py =================================================================== --- pygccxml_dev/pygccxml/declarations/cpptypes.py 2006-09-18 08:18:09 UTC (rev 548) +++ pygccxml_dev/pygccxml/declarations/cpptypes.py 2006-09-18 09:10:13 UTC (rev 549) @@ -13,8 +13,8 @@ """base class for all types""" def __init__(self): object.__init__( self ) - self.cache = algorithms_cache.type_algs_cache_t() - + self.cache = algorithms_cache.type_algs_cache_t() + def __str__(self): res = self.decl_string if res[:2]=="::": @@ -378,7 +378,9 @@ def _get_size(self): return self._size - size = property( _get_size, + def _set_size(self, size):#sometimes there is a need to update the size of the array + self._size = size + size = property( _get_size, _set_size, doc="returns array size" ) def _create_decl_string(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-18 08:18:18
|
Revision: 548 http://svn.sourceforge.net/pygccxml/?rev=548&view=rev Author: roman_yakovenko Date: 2006-09-18 01:18:09 -0700 (Mon, 18 Sep 2006) Log Message: ----------- improving pattern_parser.py Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/pattern_parser.py pygccxml_dev/unittests/call_invocation_tester.py Modified: pygccxml_dev/pygccxml/declarations/pattern_parser.py =================================================================== --- pygccxml_dev/pygccxml/declarations/pattern_parser.py 2006-09-17 08:46:42 UTC (rev 547) +++ pygccxml_dev/pygccxml/declarations/pattern_parser.py 2006-09-18 08:18:09 UTC (rev 548) @@ -66,8 +66,9 @@ if -1 == found: args.append( args_only[ previous_found : ] ) break - elif decl_string[ found ] == self.__end: - raise RuntimeError( "unmatched '%s' token has been found." % self.__end ) + #elif decl_string[ found ] == self.__end: + # print args + # raise RuntimeError( "unmatched '%s' token has been found." % self.__end ) else: args.append( args_only[ previous_found : found ] ) previous_found = found + 1 #skip found sep Modified: pygccxml_dev/unittests/call_invocation_tester.py =================================================================== --- pygccxml_dev/unittests/call_invocation_tester.py 2006-09-17 08:46:42 UTC (rev 547) +++ pygccxml_dev/unittests/call_invocation_tester.py 2006-09-18 08:18:09 UTC (rev 548) @@ -14,11 +14,11 @@ class tester_t( unittest.TestCase ): def __init__(self, *args ): unittest.TestCase.__init__( self, *args ) - + def __test_split_impl(self, decl_string, name, args): self.failUnless( ( name, args ) == declarations.call_invocation.split( decl_string ) ) - def __test_split_recursive_impl(self, decl_string, control_seq): + def __test_split_recursive_impl(self, decl_string, control_seq): self.failUnless( control_seq == declarations.call_invocation.split_recursive( decl_string ) ) def __test_is_call_invocation_impl( self, decl_string ): @@ -26,7 +26,7 @@ def test_split_on_vector(self): self.__test_is_call_invocation_impl( "vector(int,std::allocator(int) )" ) - + self.__test_split_impl( "vector(int,std::allocator(int) )" , "vector" , [ "int", "std::allocator(int)" ] ) @@ -37,14 +37,14 @@ def test_split_on_string(self): self.__test_is_call_invocation_impl( "basic_string(char,std::char_traits(char),std::allocator(char) )" ) - + self.__test_split_impl( "basic_string(char,std::char_traits(char),std::allocator(char) )" , "basic_string" , [ "char", "std::char_traits(char)", "std::allocator(char)" ] ) - + def test_split_on_map(self): self.__test_is_call_invocation_impl( "map(long int,std::vector(int, std::allocator(int) ),std::less(long int),std::allocator(std::pair(const long int, std::vector(int, std::allocator(int) ) ) ) )" ) - + self.__test_split_impl( "map(long int,std::vector(int, std::allocator(int) ),std::less(long int),std::allocator(std::pair(const long int, std::vector(int, std::allocator(int) ) ) ) )" , "map" , [ "long int" @@ -53,7 +53,7 @@ , "std::allocator(std::pair(const long int, std::vector(int, std::allocator(int) ) ) )" ] ) def test_join_on_vector(self): - self.failUnless( "vector( int, std::allocator(int) )" + self.failUnless( "vector( int, std::allocator(int) )" == declarations.call_invocation.join("vector", ( "int", "std::allocator(int)" ) ) ) def test_find_args(self): @@ -67,9 +67,15 @@ self.failUnless( (1,9) == found ) found = declarations.call_invocation.find_args( temp, found[1]+1 ) self.failUnless( (10, 14) == found ) - + + def test_bug_unmatched_brace( self ): + src = 'AlternativeName((&string("")), (&string("")), (&string("")))' + self.__test_split_impl( src + , 'AlternativeName' + , ['(&string(""))', '(&string(""))', '(&string(""))'] ) + def create_suite(): - suite = unittest.TestSuite() + suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) return suite @@ -77,4 +83,4 @@ unittest.TextTestRunner(verbosity=2).run( create_suite() ) if __name__ == "__main__": - run_suite() \ No newline at end of file + run_suite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-17 08:46:49
|
Revision: 547 http://svn.sourceforge.net/pygccxml/?rev=547&view=rev Author: roman_yakovenko Date: 2006-09-17 01:46:42 -0700 (Sun, 17 Sep 2006) Log Message: ----------- std container classes will be registered first Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-14 17:42:19 UTC (rev 546) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-17 08:46:42 UTC (rev 547) @@ -479,17 +479,8 @@ self.__extmodule.add_system_header( header ) self.__extmodule.add_include( header ) - #I am going tp find last class registration and to add all container creators - #after it. - last_cls_index = -1 - for i in range( len( self.__module_body.creators ) - 1, -1, -1 ): - if isinstance( self.__module_body.creators[i], code_creators.class_t ): - last_cls_index = i - break - insert_position = last_cls_index + 1 creators.reverse() - for creator in creators: - self.__module_body.adopt_creator( creator, insert_position ) + self.__module_body.adopt_creators( creators, 0 ) def create(self, decl_headers=None): """Create and return the module for the extension. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-14 17:42:22
|
Revision: 546 http://svn.sourceforge.net/pygccxml/?rev=546&view=rev Author: mbaas Date: 2006-09-14 10:42:19 -0700 (Thu, 14 Sep 2006) Log Message: ----------- Two bug fixes: 1) The parameter list didn't use boost::ref() etc. 2) The internal return_virtual_result_t policy didn't properly access the result value which could lead to a Python exception. Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-14 13:06:59 UTC (rev 545) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-14 17:42:19 UTC (rev 546) @@ -11,6 +11,7 @@ from pygccxml import declarations from code_manager import code_manager_t, wrapper_code_manager_t from function_transformer import function_transformer_t +from pyplusplus import decl_wrappers # substitution_manager_t class substitution_manager_t: @@ -197,7 +198,7 @@ self.virtual_func.class_name = wrapper_class self.virtual_func.FUNC_NAME = decl.name self.virtual_func.CALL_FUNC_NAME = decl.name - self.virtual_func.input_params = map(lambda a: a.name, decl.arguments) + self.virtual_func.input_params = map(lambda a: self._function_call_arg(a), decl.arguments) self.wrapper_func.arg_list = decl.arguments[:] self.wrapper_func.class_name = wrapper_class @@ -542,7 +543,40 @@ decl = parent return None + # _function_call_arg + def _function_call_arg(self, arg): + """Return the C++ expression that represents arg in the actual function call. + This helper method returns a string that contains a C++ expression + that references the argument arg. This expression is supposed to + be used in the function invocation of which this is one input + parameter. The return value is one of three variants: + + - <name> + - boost::ref(<name>) + - boost::python::ptr(<name>) + + @rtype: str + """ + arg_type = declarations.remove_alias( arg.type ) + if decl_wrappers.python_traits.is_immutable( arg_type ): + return arg.name + elif declarations.is_reference( arg_type ): + no_ref = declarations.remove_reference( arg_type ) + if decl_wrappers.python_traits.is_immutable( no_ref ): + #pass by value + return arg.name + else: + #pass by ref + return 'boost::ref(%s)' % arg.name + elif declarations.is_pointer( arg_type ) \ + and not declarations.is_pointer( arg_type.base ) \ + and not decl_wrappers.python_traits.is_immutable( arg_type.base ): + return 'boost::python::ptr(%s)' % arg.name + else: + return arg.name + + # return_virtual_result_t class return_virtual_result_t(function_transformer_t): """Extract and return the result value of the virtual function. @@ -575,13 +609,19 @@ # value of the C++ function call. If the value exists it is extracted # from the Python result tuple, converted to C++ and returned from # the virtual function. If it does not exist, do nothing. +# try: +# resultidx = sm.wrapper_func.result_exprs.index(sm.wrapper_func.result_var) +# except ValueError: +# return + try: - resultidx = sm.wrapper_func.result_exprs.index(sm.wrapper_func.result_var) + resexpr = sm.py_result_expr(self.result_var) except ValueError: return res = "// Extract the C++ return value\n" - res += "%s = boost::python::extract<%s>(%s[%d]);"%(self.result_var, sm.virtual_func.ret_type, sm.virtual_func.result_var, resultidx) + res += "%s = boost::python::extract<%s>(%s);"%(self.result_var, sm.virtual_func.ret_type, resexpr) +# res += "%s = boost::python::extract<%s>(%s[%d]);"%(self.result_var, sm.virtual_func.ret_type, sm.virtual_func.result_var, resultidx) return res This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-14 13:07:11
|
Revision: 545 http://svn.sourceforge.net/pygccxml/?rev=545&view=rev Author: mbaas Date: 2006-09-14 06:06:59 -0700 (Thu, 14 Sep 2006) Log Message: ----------- Committed the current snapshot of the function transformers. This is still work in progress and there are things missing, but it is sort of a milestone (at least for me) because I could use this version successfully for the Maya bindings where it could replace the arg policy feature from pypp_api. In this version, support for function transformers on non-virtual member functions has been implemented. Public (non-pure) virtual methods should now take the transformers into account in all cases (in the previous version it could happen that they were ignored). New policy class for in/out variables. Moved the transformed code creators to calldef_transformed.py (calldef.py is already big enough) so that the chance for conclicts on updates is reduced. Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py pyplusplus_dev/pyplusplus/function_transformers/code_manager.py pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py Added Paths: ----------- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-14 13:01:56 UTC (rev 544) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-14 13:06:59 UTC (rev 545) @@ -74,8 +74,10 @@ from calldef import copy_constructor_wrapper_t from calldef import null_constructor_wrapper_t -from calldef import mem_fun_v_transformed_t -from calldef import mem_fun_v_transformed_wrapper_t +from calldef_transformed import mem_fun_transformed_t +from calldef_transformed import mem_fun_transformed_wrapper_t +from calldef_transformed import mem_fun_v_transformed_t +from calldef_transformed import mem_fun_v_transformed_wrapper_t from global_variable import global_variable_base_t from global_variable import global_variable_t Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-09-14 13:01:56 UTC (rev 544) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-09-14 13:06:59 UTC (rev 545) @@ -10,7 +10,6 @@ import class_declaration from pygccxml import declarations from pyplusplus import decl_wrappers -import pyplusplus.function_transformers as function_transformers #virtual functions that returns const reference to something #could not be overriden by Python. The reason is simple: @@ -234,6 +233,7 @@ else: return '&%s' % declarations.full_name( self.declaration ) + class mem_fun_t( calldef_t ): def __init__( self, function ): calldef_t.__init__( self, function=function ) @@ -446,289 +446,7 @@ answer.append( self.create_default_function() ) return os.linesep.join( answer ) -class mem_fun_v_transformed_t( calldef_t ): - """Creates code for (public) virtual member functions. - """ - def __init__( self, function, wrapper=None ): - calldef_t.__init__( self, function=function, wrapper=wrapper ) - self.default_function_type_alias = 'default_' + self.function_type_alias - - def create_function_type_alias_code( self, exported_class_alias=None ): - result = [] - - ftype = self.declaration.function_type() - result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) - if self.wrapper: - result.append( os.linesep ) - ftype = self.wrapper.function_type() - result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) - return ''.join( result ) - - def create_doc(self): - return None - - def create_function_ref_code(self, use_function_alias=False): - result = [] - if use_function_alias: - result.append( '%s(&%s)' - % ( self.function_type_alias, declarations.full_name( self.declaration ) ) ) - if self.wrapper: - result.append( self.param_sep() ) - result.append( '%s(&%s)' - % ( self.default_function_type_alias, self.wrapper.default_full_name() ) ) - elif self.declaration.create_with_signature: - result.append( '(%s)(&%s)' - % ( self.declaration.function_type().decl_string - , declarations.full_name( self.declaration ) ) ) - if self.wrapper: - result.append( self.param_sep() ) - result.append( '(%s)(&%s)' - % ( self.wrapper.function_type().decl_string, self.wrapper.default_full_name() ) ) - else: - if self.wrapper: - result.append( '&%s' % self.wrapper.default_full_name() ) - else: - result.append( '&%s'% declarations.full_name( self.declaration ) ) -# result.append( '&%s'% declarations.full_name( self.declaration ) ) -# if self.wrapper: -# result.append( self.param_sep() ) -# result.append( '&%s' % self.wrapper.default_full_name() ) - return ''.join( result ) - -class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): - """Creates wrapper code for (public) virtual member functions. - - The generated code consists of two functions: the virtual function - and the 'default' function. - """ - - def __init__( self, function ): - """Constructor. - - @param function: Function declaration - @type function: calldef_t - """ - calldef_wrapper_t.__init__( self, function=function ) - - # Stores the name of the variable that holds the override - self._override_var = None - - def default_name(self): - """Return the name of the 'default' function. - - @rtype: str - """ - return "default_" + self.declaration.alias - - def default_full_name(self): - """Return the full name of the 'default' function. - - The returned name also includes the class name. - - @rtype: str - """ - return self.parent.full_name + '::default_' + self.declaration.alias - - def virtual_name(self): - """Return the name of the 'virtual' function. - - @rtype: str - """ - return self.declaration.name - - def base_name(self): - """Return the name of the 'base' function. - - @rtype: str - """ - return "base_" + self.declaration.name - - def function_type(self): - return declarations.member_function_type_t( - return_type=self.declaration.return_type - , class_inst=declarations.dummy_type_t( self.parent.full_name ) - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) - , has_const=self.declaration.has_const ) - - def create_declaration(self, name, virtual=True): - """Create the function header. - - This method is used for the virtual function (and the base_ function), - but not for the default function. - """ - template = '%(virtual)s$RET_TYPE %(name)s( $ARG_LIST_DEF )%(constness)s %(throw)s' - - # Substitute the $-variables - template = self._subst_manager.subst_virtual(template) - - virtualspec = '' - if virtual: - virtualspec = 'virtual ' - - constness = '' - if self.declaration.has_const: - constness = ' const ' - - return template % { - 'virtual' : virtualspec - , 'name' : name - , 'constness' : constness - , 'throw' : self.throw_specifier_code() - } - - def create_base_body(self): - body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" - - return_ = '' - if not declarations.is_void( self.declaration.return_type ): - return_ = 'return ' - - return body % { - 'name' : self.declaration.name - , 'args' : self.function_call_args() - , 'return_' : return_ - , 'wrapped_class' : self.wrapped_class_identifier() - } - - def create_virtual_body(self): - - body = """ -$DECLARATIONS - -if( %(override_var)s ) -{ - $PRE_CALL - - ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); - - $POST_CALL - - $RETURN_STMT -} -else -{ - %(inherited)s -} -""" - - vf = self._subst_manager.virtual_func - arg0 = "%s.ptr()"%self._override_var - if vf.INPUT_PARAMS=="": - vf.INPUT_PARAMS = arg0 - else: - vf.INPUT_PARAMS = arg0+", "+vf.INPUT_PARAMS - - # Replace the $-variables - body = self._subst_manager.subst_virtual(body) - -# template = [] -# template.append( 'if( %(override)s func_%(alias)s = this->get_override( "%(alias)s" ) )' ) -# template.append( self.indent('%(return_)sfunc_%(alias)s( %(args)s );') ) -# template.append( 'else' ) -# template.append( self.indent('%(return_)s%(wrapped_class)s::%(name)s( %(args)s );') ) -# template = os.linesep.join( template ) - - return body % { -# 'override' : self.override_identifier() - 'override_var' : self._override_var - , 'alias' : self.declaration.alias -# , 'func_var' : "func_"+self.declaration.alias - , 'inherited' : self.create_base_body() - } - - def create_default_body(self): - cls_wrapper_type = self.parent.full_name - cls_wrapper = self._subst_manager.wrapper_func.declare_local("cls_wrapper", cls_wrapper_type); - # The name of the 'self' variable (i.e. first argument) - selfname = self._subst_manager.wrapper_func.arg_list[0].name - - body = """$DECLARATIONS - -$PRE_CALL - -%(cls_wrapper_type)s* %(cls_wrapper)s = dynamic_cast<%(cls_wrapper_type)s*>(&%(self)s); -if (%(cls_wrapper)s==0) -{ - // The following call is done on an instance created in C++, - // so it won't invoke Python code. - $RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS); -} -else -{ - // The following call is done on an instance created in Python, - // i.e. a wrapper instance. This call might invoke Python code. - $RESULT_VAR_ASSIGNMENT%(cls_wrapper)s->%(base_name)s($INPUT_PARAMS); -} - -$POST_CALL - -$RETURN_STMT -""" - - # Replace the $-variables - body = self._subst_manager.subst_wrapper(body) - - # Replace the remaining parameters - body = body%{"cls_wrapper_type" : cls_wrapper_type, - "cls_wrapper" : cls_wrapper, - "self" : selfname, - "base_name" : self.base_name() } - -# function_call = declarations.call_invocation.join( self.declaration.name -# , [ self.function_call_args() ] ) -# body = self.wrapped_class_identifier() + '::' + function_call + ';' -# if not declarations.is_void( self.declaration.return_type ): -# body = 'return ' + body - return body - - def create_function(self): - answer = [ self.create_declaration(self.declaration.name) + '{' ] - answer.append( self.indent( self.create_virtual_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - - def create_base_function( self ): - answer = [ self.create_declaration("base_"+self.declaration.name, False) + '{' ] - body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" - answer.append( self.indent( self.create_base_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - - def create_default_function( self ): - - header = 'static $RET_TYPE %s( $ARG_LIST_DEF ) {'%self.default_name() - header = self._subst_manager.subst_wrapper(header) - - answer = [ header ] - answer.append( self.indent( self.create_default_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - - - def _create_impl(self): - # Create the substitution manager - decl = self.declaration - sm = function_transformers.substitution_manager_t(decl, transformers=decl.function_transformers) - self._override_var = sm.virtual_func.declare_local(decl.alias+"_callable", "boost::python::override", default='this->get_override( "%s" )'%decl.alias) - self._subst_manager = sm - - answer = [ self.create_function() ] - answer.append( os.linesep ) - answer.append( self.create_base_function() ) - answer.append( os.linesep ) - answer.append( self.create_default_function() ) - answer = os.linesep.join( answer ) - - # Replace the argument list of the declaration so that in the - # case that keywords are created, the correct arguments will be - # picked up (i.e. the modified argument list and not the original - # argument list) - self.declaration.arguments = self._subst_manager.wrapper_func.arg_list - - return answer - - class mem_fun_protected_t( calldef_t ): def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) Added: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-09-14 13:06:59 UTC (rev 545) @@ -0,0 +1,496 @@ +# 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) + +import os +#import algorithm +#import code_creator +#import class_declaration +from pygccxml import declarations +from calldef import calldef_t, calldef_wrapper_t +import pyplusplus.function_transformers as function_transformers + +###################################################################### + +class mem_fun_transformed_t( calldef_t ): + """Creates code for public non-virtual member functions. + """ + + def __init__( self, function, wrapper=None ): + calldef_t.__init__( self, function=function, wrapper=wrapper ) + + def create_function_type_alias_code( self, exported_class_alias=None ): + if self.wrapper==None: + ftype = self.declaration.function_type() + else: + ftype = self.wrapper.function_type() + res = 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) + return res + + def create_function_ref_code(self, use_function_alias=False): + if self.wrapper: + full_name = self.wrapper.full_name() + else: + full_name = declarations.full_name( self.declaration ) + + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, full_name ) + elif self.declaration.create_with_signature: + if self.wrapper: + func_type = self.wrapper.function_type() + else: + func_type = self.declaration.function_type().decl_string + return '(%s)( &%s )' \ + % ( func_type, full_name ) + else: + return '&%s' % full_name + + +class mem_fun_transformed_wrapper_t( calldef_wrapper_t ): + """Creates wrapper code for (public) non-virtual member functions. + + The generated function is either used as a static member inside the + wrapper class (when self.parent is not None) or as a free function + (when self.parent is None). + """ + + def __init__( self, function ): + """Constructor. + + @param function: Function declaration + @type function: calldef_t + """ + calldef_wrapper_t.__init__( self, function=function ) + +# def is_free_function(self): +# """Return True if the generated function is a free function. +# +# @rtype: bool +# """ +# return self.parent==None + + def function_type(self): + """Return the type of the wrapper function. + + @rtype: type_t + """ + template = '$RET_TYPE' + rettype = self._subst_manager.subst_wrapper(template) + rettype = declarations.dummy_type_t(rettype) + + return declarations.free_function_type_t( + return_type=rettype + , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) ) + + + def full_name(self): + """Return the full name of the wrapper function. + + The returned name also includes the class name (if there is any). + + @rtype: str + """ + if self.parent==None: + return '_py_' + self.declaration.alias + else: + return self.parent.full_name + '::_py_' + self.declaration.alias + + def create_sig_id(self): + """Create an ID string that identifies a signature. + + @rtype: str + """ + template = '%s($ARG_LIST_TYPES)'%self.declaration.alias + return self._subst_manager.subst_wrapper(template) + + def create_declaration(self, name): + """Create the function header. + """ + template = 'static $RET_TYPE %(name)s( $ARG_LIST_DEF ) %(throw)s' + + # Substitute the $-variables + template = self._subst_manager.subst_wrapper(template) + + return template % { + 'name' : "_py_"+name + , 'throw' : self.throw_specifier_code() + } + + def create_body(self): + + body = """ +$DECLARATIONS + +$PRE_CALL + +$RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS); + +$POST_CALL + +$RETURN_STMT +""" + + # Replace the $-variables + body = self._subst_manager.subst_wrapper(body) + + return body + + def create_function(self): +# sig_id = self.create_sig_id() + # ...check sig here... + + answer = [70*"/"] + answer.append("// Transformed wrapper function for:") + answer.append("// %s"%self.declaration) + answer.append(70*"/") + answer.append( self.create_declaration(self.declaration.alias) + '{') + answer.append( self.indent( self.create_body() ) ) + answer.append( '}' ) + return os.linesep.join( answer ) + + def _create_impl(self): + # Create the substitution manager + decl = self.declaration + sm = function_transformers.substitution_manager_t(decl, transformers=decl.function_transformers) + self._subst_manager = sm + + answer = self.create_function() + + # Replace the argument list of the declaration so that in the + # case that keywords are created, the correct arguments will be + # picked up (i.e. the modified argument list and not the original + # argument list) + self.declaration.arguments = self._subst_manager.wrapper_func.arg_list + + return answer + +###################################################################### + +class mem_fun_v_transformed_t( calldef_t ): + """Creates code for (public) virtual member functions. + """ + + def __init__( self, function, wrapper=None ): + calldef_t.__init__( self, function=function, wrapper=wrapper ) + self.default_function_type_alias = 'default_' + self.function_type_alias + + def create_function_type_alias_code( self, exported_class_alias=None ): + if self.wrapper==None: + ftype = self.declaration.function_type() + else: + ftype = self.wrapper.function_type() + + result = [] + result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) + return ''.join( result ) + + def create_doc(self): + return None + + def create_function_ref_code(self, use_function_alias=False): + if self.wrapper: + full_name = self.wrapper.default_full_name() + else: + full_name = declarations.full_name( self.declaration ) + + result = [] + if use_function_alias: + result.append( '%s(&%s)' + % ( self.function_type_alias, full_name ) ) + elif self.declaration.create_with_signature: + if self.wrapper: + func_type = self.wrapper.function_type() + else: + func_type = self.declaration.function_type().decl_string + result.append( '(%s)(&%s)' + % ( func_type, full_name ) ) + else: + result.append( '&%s' % full_name ) + + return ''.join( result ) + + +class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): + """Creates wrapper code for (public) virtual member functions. + + The generated code consists of two functions: the virtual function + and the 'default' function. + """ + + def __init__( self, function ): + """Constructor. + + @param function: Function declaration + @type function: calldef_t + """ + calldef_wrapper_t.__init__( self, function=function ) + + # Stores the name of the variable that holds the override + self._override_var = None + + def default_name(self): + """Return the name of the 'default' function. + + @rtype: str + """ + return "default_" + self.declaration.alias + + def default_full_name(self): + """Return the full name of the 'default' function. + + The returned name also includes the class name. + + @rtype: str + """ + return self.parent.full_name + '::default_' + self.declaration.alias + + def virtual_name(self): + """Return the name of the 'virtual' function. + + @rtype: str + """ + return self.declaration.name + + def base_name(self): + """Return the name of the 'base' function. + + @rtype: str + """ + return "base_" + self.declaration.name + + def function_type(self): + template = '$RET_TYPE' + rettype = self._subst_manager.subst_wrapper(template) + rettype = declarations.dummy_type_t(rettype) + + return declarations.free_function_type_t( + return_type=rettype + , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) ) + + return declarations.member_function_type_t( + return_type=self.declaration.return_type + , class_inst=declarations.dummy_type_t( self.parent.full_name ) + , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) + , has_const=self.declaration.has_const ) + + def create_declaration(self, name, virtual=True): + """Create the function header. + + This method is used for the virtual function (and the base_ function), + but not for the default function. + """ + template = '%(virtual)s$RET_TYPE %(name)s( $ARG_LIST_DEF )%(constness)s %(throw)s' + + # Substitute the $-variables + template = self._subst_manager.subst_virtual(template) + + virtualspec = '' + if virtual: + virtualspec = 'virtual ' + + constness = '' + if self.declaration.has_const: + constness = ' const ' + + return template % { + 'virtual' : virtualspec + , 'name' : name + , 'constness' : constness + , 'throw' : self.throw_specifier_code() + } + + def create_base_body(self): + body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" + + return_ = '' + if not declarations.is_void( self.declaration.return_type ): + return_ = 'return ' + + return body % { + 'name' : self.declaration.name + , 'args' : self.function_call_args() + , 'return_' : return_ + , 'wrapped_class' : self.wrapped_class_identifier() + } + + def create_virtual_body(self): + + thread_safe = False + + if thread_safe: + # Todo: Properly allocate "gstate" + body = """ +PyGILState_STATE gstate; +gstate = PyGILState_Ensure(); + +$DECLARATIONS + +PyGILState_Release(gstate); + +if( %(override_var)s ) +{ + gstate = PyGILState_Ensure(); + + try { + $PRE_CALL + + ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); + + $POST_CALL + } + catch(...) + { + if (PyErr_Occurred()) + { + PyErr_Print(); + } + PyGILState_Release(gstate); + throw; + } + PyGILState_Release(gstate); + $RETURN_STMT +} +else +{ + %(inherited)s +} +""" + + if not thread_safe: + body = """ +$DECLARATIONS + +if( %(override_var)s ) +{ + $PRE_CALL + + ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); + + $POST_CALL + + $RETURN_STMT +} +else +{ + %(inherited)s +} +""" + + vf = self._subst_manager.virtual_func + arg0 = "%s.ptr()"%self._override_var + if vf.INPUT_PARAMS=="": + vf.INPUT_PARAMS = arg0 + else: + vf.INPUT_PARAMS = arg0+", "+vf.INPUT_PARAMS + + # Replace the $-variables + body = self._subst_manager.subst_virtual(body) + +# template = [] +# template.append( 'if( %(override)s func_%(alias)s = this->get_override( "%(alias)s" ) )' ) +# template.append( self.indent('%(return_)sfunc_%(alias)s( %(args)s );') ) +# template.append( 'else' ) +# template.append( self.indent('%(return_)s%(wrapped_class)s::%(name)s( %(args)s );') ) +# template = os.linesep.join( template ) + + return body % { +# 'override' : self.override_identifier() + 'override_var' : self._override_var + , 'alias' : self.declaration.alias +# , 'func_var' : "func_"+self.declaration.alias + , 'inherited' : self.create_base_body() + } + + def create_default_body(self): + cls_wrapper_type = self.parent.full_name + cls_wrapper = self._subst_manager.wrapper_func.declare_local("cls_wrapper", cls_wrapper_type); + # The name of the 'self' variable (i.e. first argument) + selfname = self._subst_manager.wrapper_func.arg_list[0].name + + body = """$DECLARATIONS + +$PRE_CALL + +%(cls_wrapper_type)s* %(cls_wrapper)s = dynamic_cast<%(cls_wrapper_type)s*>(boost::addressof(%(self)s)); +if (%(cls_wrapper)s==0) +{ + // The following call is done on an instance created in C++, + // so it won't invoke Python code. + $RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS); +} +else +{ + // The following call is done on an instance created in Python, + // i.e. a wrapper instance. This call might invoke Python code. + $RESULT_VAR_ASSIGNMENT%(cls_wrapper)s->%(base_name)s($INPUT_PARAMS); +} + +$POST_CALL + +$RETURN_STMT +""" + + # Replace the $-variables + body = self._subst_manager.subst_wrapper(body) + + # Replace the remaining parameters + body = body%{"cls_wrapper_type" : cls_wrapper_type, + "cls_wrapper" : cls_wrapper, + "self" : selfname, + "base_name" : self.base_name() } + +# function_call = declarations.call_invocation.join( self.declaration.name +# , [ self.function_call_args() ] ) +# body = self.wrapped_class_identifier() + '::' + function_call + ';' +# if not declarations.is_void( self.declaration.return_type ): +# body = 'return ' + body + return body + + def create_function(self): + answer = [ self.create_declaration(self.declaration.name) + '{' ] + answer.append( self.indent( self.create_virtual_body() ) ) + answer.append( '}' ) + return os.linesep.join( answer ) + + def create_base_function( self ): + answer = [ self.create_declaration("base_"+self.declaration.name, False) + '{' ] + body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" + answer.append( self.indent( self.create_base_body() ) ) + answer.append( '}' ) + return os.linesep.join( answer ) + + def create_default_function( self ): + + header = 'static $RET_TYPE %s( $ARG_LIST_DEF ) {'%self.default_name() + header = self._subst_manager.subst_wrapper(header) + + answer = [ header ] + answer.append( self.indent( self.create_default_body() ) ) + answer.append( '}' ) + return os.linesep.join( answer ) + + + def _create_impl(self): + # Create the substitution manager + decl = self.declaration + sm = function_transformers.substitution_manager_t(decl, transformers=decl.function_transformers) + self._override_var = sm.virtual_func.declare_local(decl.alias+"_callable", "boost::python::override", default='this->get_override( "%s" )'%decl.alias) + self._subst_manager = sm + + answer = [ self.create_function() ] + answer.append( os.linesep ) + answer.append( self.create_base_function() ) + answer.append( os.linesep ) + answer.append( self.create_default_function() ) + answer = os.linesep.join( answer ) + + # Replace the argument list of the declaration so that in the + # case that keywords are created, the correct arguments will be + # picked up (i.e. the modified argument list and not the original + # argument list) + self.declaration.arguments = self._subst_manager.wrapper_func.arg_list + + return answer + Property changes on: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py ___________________________________________________________________ Name: svn:eol-style + native Modified: pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-09-14 13:01:56 UTC (rev 544) +++ pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-09-14 13:06:59 UTC (rev 545) @@ -11,6 +11,7 @@ - L{output_t} - L{input_t} + - L{inout_t} - L{input_array_t} - L{output_array_t} """ @@ -105,14 +106,73 @@ reftype = arg.type if not (isinstance(reftype, declarations.reference_t) or isinstance(reftype, declarations.pointer_t)): - raise ValueError, 'Output variable %d ("%s") must be a reference or a pointer (got %s)'%(self.idx, arg.name, arg.type) + raise ValueError, 'Input variable %d ("%s") must be a reference or a pointer (got %s)'%(self.idx, arg.name, arg.type) # Create an equivalent argument that is not a reference type noref_arg = declarations.argument_t(name=arg.name, type=arg.type.base, default_value=arg.default_value) # Insert the noref argument sm.insert_arg(self.idx, noref_arg, arg.name) +# inout_t +class inout_t: + """Handles a single input/output variable. + void foo(int& v) -> v = foo(v) + """ + + def __init__(self, idx): + """Constructor. + + The specified argument must be a reference or a pointer. + + @param idx: Index of the argument that is an in/out value (the first arg has index 1). + @type idx: int + """ + self.idx = idx + self.local_var = "<not initialized>" + + def __str__(self): + return "InOut(%d)"%(self.idx) + + def init_funcs(self, sm): + # Remove the specified input argument from the wrapper function + arg = sm.remove_arg(self.idx) + + # Do some checks (the arg has to be a reference or a pointer) + reftype = arg.type + if not (isinstance(reftype, declarations.reference_t) or + isinstance(reftype, declarations.pointer_t)): + raise ValueError, 'InOut variable %d ("%s") must be a reference or a pointer (got %s)'%(self.idx, arg.name, arg.type) + + # Create an equivalent argument that is not a reference type + noref_arg = declarations.argument_t(name=arg.name, type=arg.type.base, default_value=arg.default_value) + # Insert the noref argument + sm.insert_arg(self.idx, noref_arg, arg.name) + + # Use the input arg to also store the output + self.local_var = noref_arg.name + # Append the output to the result tuple + sm.wrapper_func.result_exprs.append(self.local_var) + + # Replace the expression in the C++ function call + if isinstance(reftype, declarations.pointer_t): + sm.wrapper_func.input_params[self.idx-1] = "&%s"%self.local_var + else: + sm.wrapper_func.input_params[self.idx-1] = self.local_var + + + def virtual_post_call(self, sm): + """Extract the C++ value after the call to the Python function. + """ + arg = sm.virtual_func.arg_list[self.idx-1] + res = "// Extract the C++ value for in/out argument '%s' (index: %d)\n"%(arg.name, self.idx) + if isinstance(arg.type, declarations.pointer_t): + res += "*" + res += "%s = boost::python::extract<%s>(%s);"%(arg.name, arg.type.base, sm.py_result_expr(self.local_var)) + return res + + + # input_array_t class input_array_t: """Handles an input array with fixed size. @@ -160,7 +220,7 @@ self.pylist = sm.virtual_func.declare_local("py_"+arg.name, "boost::python::list") # Replace the removed argument with a Python object. - newarg = declarations.argument_t(arg.name, "boost::python::object") + newarg = declarations.argument_t(arg.name, declarations.dummy_type_t("boost::python::object")) sm.insert_arg(self.idx, newarg, self.pylist) self.argname = arg.name Modified: pyplusplus_dev/pyplusplus/function_transformers/code_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-09-14 13:01:56 UTC (rev 544) +++ pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-09-14 13:06:59 UTC (rev 545) @@ -35,7 +35,7 @@ @ivar ret_type: Return type. The value may be any object where str(obj) is valid C++ code. The value None corresponds to void. This will be the value of the variable RET_TYPE. @type ret_type: str @ivar arg_list: The argument list. The items are pygccxml argument_t objects. This list will appear in the variables ARG_LIST, ARG_LIST_DEF and ARG_LIST_TYPES. - @type arg_list: list of argument_t + @type arg_list: list of L{argument_t<pygccxml.declarations.calldef.argument_t>} @ivar input_params: A list of strings that contain the input parameter for the function call. This list is used for the INPUT_PARAMS variable. @type input_params: list of str @ivar result_var: The name of the variable that will receive the result of the function call. If None, the return value is ignored. This attribute will be used for the variable RESULT_VAR_ASSIGNMENT. @@ -225,8 +225,8 @@ which is a list of individual expressions. Apart from that this class is identical to L{code_manager_t}. - @ivar result_exprs: Similar to result_expr but this list variable can contain more than just one result. The items can be either strings containing the variable names (or expressions) that should be returned or it can be an argument_t object (usually from the argument list of the virtual function) whose name attribute will be used. This attribute only exists on the code manager for the wrapper function (the virtual function cannot return several values, use result_expr instead). - @type result_exprs: list of str or argument_t + @ivar result_exprs: Similar to result_expr but this list variable can contain more than just one result. The items can be either strings containing the variable names (or expressions) that should be returned or it can be an L{argument_t<pygccxml.declarations.calldef.argument_t>} object (usually from the argument list of the virtual function) whose name attribute will be used. This attribute only exists on the code manager for the wrapper function (the virtual function cannot return several values, use result_expr instead). + @type result_exprs: list of str or L{argument_t<pygccxml.declarations.calldef.argument_t>} """ def __init__(self): Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-14 13:01:56 UTC (rev 544) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-14 13:06:59 UTC (rev 545) @@ -192,29 +192,31 @@ self._wrapper_includes = [] # Initialize the code managers... - - if str(decl.return_type)=="void": - ret_type = None - else: - ret_type = decl.return_type - self.wrapper_func.result_type = str(ret_type) - self.wrapper_func.result_var = self.wrapper_func.declare_local("result", self.wrapper_func.result_type) - self.wrapper_func.result_exprs = [self.wrapper_func.result_var] - self.virtual_func.ret_type = ret_type self.virtual_func.arg_list = decl.arguments[:] self.virtual_func.class_name = wrapper_class self.virtual_func.FUNC_NAME = decl.name self.virtual_func.CALL_FUNC_NAME = decl.name self.virtual_func.input_params = map(lambda a: a.name, decl.arguments) - self.wrapper_func.ret_type = ret_type self.wrapper_func.arg_list = decl.arguments[:] self.wrapper_func.class_name = wrapper_class self.wrapper_func.FUNC_NAME = "%s_wrapper"%decl.alias self.wrapper_func.CALL_FUNC_NAME = decl.name self.wrapper_func.input_params = map(lambda a: a.name, decl.arguments) + if str(decl.return_type)=="void": + ret_type = None + else: + ret_type = decl.return_type + self.wrapper_func.result_type = str(ret_type) + self.wrapper_func.result_var = self.wrapper_func.declare_local("result", self.wrapper_func.result_type) + self.wrapper_func.result_exprs = [self.wrapper_func.result_var] + + self.virtual_func.ret_type = ret_type + + self.wrapper_func.ret_type = ret_type + # The offset that is added to the index in insert_arg() # This index is either 0 for free functions or 1 for member functions # because the "self" argument is not a regular argument. @@ -224,7 +226,7 @@ clsdecl = self._class_decl(decl) if clsdecl!=None: selfname = self.wrapper_func._make_name_unique("self") - selfarg = declarations.argument_t(selfname, "%s&"%clsdecl.name) + selfarg = declarations.argument_t(selfname, declarations.dummy_type_t("%s&"%clsdecl.name)) self.wrapper_func.arg_list.insert(0, selfarg) self.wrapper_func.CALL_FUNC_NAME = "%s.%s"%(selfname, self.wrapper_func.CALL_FUNC_NAME) self._insert_arg_idx_offset = 1 @@ -256,6 +258,8 @@ It is not necessary to call this method manually, it is automatically called at the time a substitution is requested. """ +# print "Transforming:",self.decl +# print " using transformers:", ", ".join(map(lambda x: str(x), self.transformers)) # Append the default return_virtual_result_t code modifier transformers = self.transformers+[return_virtual_result_t()] @@ -335,6 +339,7 @@ if idx==0: if id(self.wrapper_func.ret_type)==id(self.wrapper_func.ret_type): self.wrapper_func.ret_type = None + self.wrapper_func.result_exprs.remove(self.wrapper_func.result_var) else: raise ValueError, 'Argument %d not found on the wrapper function'%(idx) # Remove argument... @@ -345,7 +350,9 @@ try: self.wrapper_func.arg_list.remove(arg) except ValueError: - raise ValueError, 'Argument %d ("%s") not found on the wrapper function'%(idx, arg.name) + msg = str(self.decl)+"\n" + msg += 'Argument %d ("%s") not found on the wrapper function'%(idx, arg.name) + raise ValueError, msg # Remove the input parameter on the Python call in the # virtual function. Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-14 13:01:56 UTC (rev 544) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-14 13:06:59 UTC (rev 545) @@ -546,6 +546,19 @@ maker = maker_cls( function=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) + # Are we dealing with transformed non-virtual member functions? + if maker_cls==code_creators.mem_fun_transformed_t: + # Create the code creator that generates the function source code + mftw = code_creators.mem_fun_transformed_wrapper_t(self.curr_decl) + # and add it either to the wrapper class or just to the declaration + # area of the cpp file + if self.curr_code_creator.wrapper is None: + self.curr_code_creator.associated_decl_creators.append(mftw) + else: + self.curr_code_creator.wrapper.adopt_creator(mftw) + # Set the wrapper so that the registration code will refer to it + maker.wrapper = mftw + if self.curr_decl.has_static: #static_method should be created only once. found = filter( lambda creator: isinstance( creator, code_creators.static_method_t ) Modified: pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py 2006-09-14 13:01:56 UTC (rev 544) +++ pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py 2006-09-14 13:06:59 UTC (rev 545) @@ -22,7 +22,10 @@ access_level = decl.parent.find_out_member_access_type( decl ) if access_level == ACCESS_TYPES.PUBLIC: if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: - maker_cls = code_creators.mem_fun_t + if decl.function_transformers: + maker_cls = code_creators.mem_fun_transformed_t + else: + maker_cls = code_creators.mem_fun_t elif decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: fwrapper_cls = code_creators.mem_fun_pv_wrapper_t maker_cls = code_creators.mem_fun_pv_t This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-14 13:02:09
|
Revision: 544 http://svn.sourceforge.net/pygccxml/?rev=544&view=rev Author: roman_yakovenko Date: 2006-09-14 06:01:56 -0700 (Thu, 14 Sep 2006) Log Message: ----------- small refactoring to clean creator_t class. Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-09-14 12:02:53 UTC (rev 543) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-09-14 13:01:56 UTC (rev 544) @@ -90,10 +90,10 @@ if None is self._equality_comparable: self._equality_comparable = declarations.has_public_equal( self ) return self._equality_comparable - + def _set_equality_comparable( self, value ): self._equality_comparable = value - + equality_comparable = property( _get_equality_comparable, _set_equality_comparable , doc="indicates existence of public operator=" \ +"Default value is calculated, based on information presented in the declarations tree" ) @@ -137,7 +137,7 @@ self._null_constructor_body = '' self._copy_constructor_body = '' self._exception_translation_code = None - + def _get_redefine_operators( self ): return self._redefine_operators def _set_redefine_operators( self, new_value ): @@ -211,7 +211,7 @@ @property def exception_argument_name( self ): """exception argument name for translate exception function - + If you don't understand what this argument is, please take a look on Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/exception_translator.html """ @@ -221,7 +221,7 @@ return self._exception_translation_code def _set_exception_translation_code( self, code ): self._exception_translation_code = code - exception_translation_code = property( _get_exception_translation_code, _set_exception_translation_code + exception_translation_code = property( _get_exception_translation_code, _set_exception_translation_code , doc="C++ exception to Python exception translation code" \ +"\nExample: PyErr_SetString(PyExc_RuntimeError, exc.what()); " \ +"\nPy++ will generate the rest of the code." \ @@ -229,29 +229,29 @@ def translate_exception_to_string( self, python_exception_type, to_string ): """registers exception translation to string - + @param python_exception_type: Python exception type, for example PyExc_RuntimeError @type python_exception_type: str - - @param to_string: C++ expression that extracts information from exception. + + @param to_string: C++ expression that extracts information from exception. The type of expression should be char*. @type to_string: str """ - #NICE TO HAVE: + #NICE TO HAVE: #1. exception\assert\warning should be raised if python_exception_type # does not contain valid Python exception #2. Py++ can validate, that member function returns char* code = "PyErr_SetString( %(exception_type)s, %(to_string)s ); " \ % { 'exception_type' : python_exception_type, 'to_string' : to_string } self.exception_translation_code = code - + def add_declaration_code( self, code ): """adds the code to the declaration section""" self.declaration_code.append( user_text.user_text_t( code ) ) def add_registration_code( self, code, works_on_instance=True ): """adds the code to the class registration section - + works_on_instance: If true, the custom code can be applied directly to obj inst. Example: ObjInst."CustomCode" """ @@ -278,3 +278,35 @@ if not self in self.parent.public_members: return 'Py++ can not expose private class.' return '' + + def get_exportable_members( self, sort=None ): + """returns list of internal declarations that should\\could be exported""" + #TODO: obviously this function should be shorter. Almost all logic of this class + # should be spread between decl_wrapper classes + members = filter( lambda mv: mv.ignore == False and mv.exportable, self.public_members ) + #protected and private virtual functions that not overridable and not pure + #virtual should not be exported + for member in self.protected_members: + if not isinstance( member, declarations.calldef_t ): + continue + else: + members.append( member ) + + vfunction_selector = lambda member: isinstance( member, declarations.member_function_t ) \ + and member.virtuality == declarations.VIRTUALITY_TYPES.PURE_VIRTUAL + members.extend( filter( vfunction_selector, self.private_members ) ) + #now lets filter out none public operators: Py++ does not support them right now + members = filter( lambda decl: not isinstance( decl, declarations.member_operator_t ) + or decl.access_type == declarations.ACCESS_TYPES.PUBLIC + , members ) + #-#if declarations.has_destructor( self ) \ + #-# and not declarations.has_public_destructor( self ): + #remove artificial constructors + members = filter( lambda decl: not isinstance( decl, declarations.constructor_t ) + or not decl.is_artificial + , members ) + members = filter( lambda member: member.ignore == False and member.exportable, members ) + sorted_members = members + if sort: + sorted_members = sort( members ) + return sorted_members Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-09-14 12:02:53 UTC (rev 543) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-09-14 13:01:56 UTC (rev 544) @@ -97,6 +97,9 @@ self._exportable_reason = 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' elif self.location and self.location.file_name == "<internal>": self._exportable_reason = 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' + elif self.is_artificial \ + and not isinstance( self, ( declarations.class_t, declarations.enumeration_t ) ): + self._exportable_reason = 'Py++, by default, does not expose compiler generated declarations.' else: self._exportable_reason = self._exportable_impl( ) self._exportable = not bool( self._exportable_reason ) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-14 12:02:53 UTC (rev 543) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-14 13:01:56 UTC (rev 544) @@ -45,7 +45,13 @@ INDEXING_SUITE_2_MAIN_HEADER = "boost/python/suite/indexing/container_suite.hpp" -DO_NOT_REPORT_MSGS = [ "Py++ does not exports compiler generated constructors" ] +DO_NOT_REPORT_MSGS = [ + "Py++ does not exports compiler generated constructors" + , 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' + , 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' + , 'Py++, by default, does not expose compiler generated declarations.' + , 'Py++ can not expose private class.' +] class creator_t( declarations.decl_visitor_t ): """Creating code creators. @@ -117,7 +123,7 @@ self.__extmodule.adopt_creator( self.__module_body ) prepared_decls = self._prepare_decls( decls, doc_extractor ) - self.__decls = self._filter_decls( self._reorder_decls( prepared_decls ) ) + self.__decls = self._reorder_decls( prepared_decls ) self.curr_code_creator = self.__module_body self.curr_decl = None @@ -163,7 +169,6 @@ for msg in readme: self.decl_logger.warn( "%s;%s" % ( decl, msg ) ) - #leave only declarations defined under namespace, but remove namespaces decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \ and isinstance( x.parent, declarations.namespace_t ) @@ -217,48 +222,6 @@ new_ordered.extend( variables ) return new_ordered # - def _exportable_class_members( self, class_decl ): - assert isinstance( class_decl, declarations.class_t ) - members = filter( lambda mv: mv.ignore == False and mv.exportable, class_decl.public_members ) - #protected and private virtual functions that not overridable and not pure - #virtual should not be exported - for member in class_decl.protected_members: - if not isinstance( member, declarations.calldef_t ): - continue - else: - members.append( member ) - - vfunction_selector = lambda member: isinstance( member, declarations.member_function_t ) \ - and member.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL - members.extend( filter( vfunction_selector, class_decl.private_members ) ) - #now lets filter out none public operators: Py++ does not support them right now - members = filter( lambda decl: not isinstance( decl, declarations.member_operator_t ) - or decl.access_type == ACCESS_TYPES.PUBLIC - , members ) - #-#if declarations.has_destructor( class_decl ) \ - #-# and not declarations.has_public_destructor( class_decl ): - #remove artificial constructors - members = filter( lambda decl: not isinstance( decl, declarations.constructor_t ) - or not decl.is_artificial - , members ) - members = filter( lambda member: member.ignore == False and member.exportable, members ) - ordered_members = self._reorder_decls( members ) - return ordered_members - - def _does_class_have_smth_to_export(self, exportable_members ): - return bool( self._filter_decls( exportable_members ) ) - - def _filter_decls( self, decls ): - # Filter out artificial (compiler created) types unless they are classes - # See: http://public.kitware.com/pipermail/gccxml/2004-October/000486.html - decls = filter( lambda x: not (x.is_artificial and - not (isinstance(x, ( declarations.class_t, declarations.enumeration_t)))) - , decls ) - # Filter out type defs - decls = filter( lambda x: not isinstance( x, declarations.typedef_t ), decls ) - - return decls - def __is_same_func( self, f1, f2 ): if not f1.__class__ is f2.__class__: return False @@ -602,7 +565,7 @@ self.__module_body.adopt_creator( maker ) cwrapper = None - exportable_members = self._exportable_class_members(self.curr_code_creator.declaration) + exportable_members = self.curr_code_creator.declaration.get_exportable_members() if self._is_wrapper_needed( self.curr_decl.parent, exportable_members ): class_wrapper = self.curr_code_creator.wrapper cwrapper = code_creators.constructor_wrapper_t( constructor=self.curr_decl ) @@ -710,7 +673,7 @@ assert isinstance( self.curr_decl, declarations.class_t ) cls_decl = self.curr_decl cls_parent_cc = self.curr_code_creator - exportable_members = self._exportable_class_members(self.curr_decl) + exportable_members = self.curr_decl.get_exportable_members(self._reorder_decls) wrapper = None cls_cc = code_creators.class_t( class_inst=self.curr_decl ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-14 12:03:04
|
Revision: 543 http://svn.sourceforge.net/pygccxml/?rev=543&view=rev Author: roman_yakovenko Date: 2006-09-14 05:02:53 -0700 (Thu, 14 Sep 2006) Log Message: ----------- moving guess_mem_fun_creator_classes from code_creators to module_creator package Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/module_creator/creator.py Added Paths: ----------- pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-14 06:19:18 UTC (rev 542) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-14 12:02:53 UTC (rev 543) @@ -118,54 +118,3 @@ from exception_translator import exception_translator_t from exception_translator import exception_translator_register_t - -from pygccxml import declarations - -ACCESS_TYPES = declarations.ACCESS_TYPES -VIRTUALITY_TYPES = declarations.VIRTUALITY_TYPES - - -def guess_mem_fun_creator_classes( decl ): - """return tuple of ( registration, declaration ) code creator classes""" - maker_cls = None - fwrapper_cls = None - access_level = decl.parent.find_out_member_access_type( decl ) - if access_level == ACCESS_TYPES.PUBLIC: - if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: - maker_cls = mem_fun_t - elif decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: - fwrapper_cls = mem_fun_pv_wrapper_t - maker_cls = mem_fun_pv_t - else: - if decl.function_transformers: - fwrapper_cls = mem_fun_v_transformed_wrapper_t - maker_cls = mem_fun_v_transformed_t - else: - if decl.overridable: - fwrapper_cls = mem_fun_v_wrapper_t - maker_cls = mem_fun_v_t - elif access_level == ACCESS_TYPES.PROTECTED: - if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: - if decl.has_static: - fwrapper_cls = mem_fun_protected_s_wrapper_t - maker_cls = mem_fun_protected_s_t - else: - fwrapper_cls = mem_fun_protected_wrapper_t - maker_cls = mem_fun_protected_t - elif decl.virtuality == VIRTUALITY_TYPES.VIRTUAL: - if decl.overridable: - fwrapper_cls = mem_fun_protected_v_wrapper_t - maker_cls = mem_fun_protected_v_t - else: - fwrapper_cls = mem_fun_protected_pv_wrapper_t - maker_cls = mem_fun_protected_pv_t - else: #private - if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: - pass#in general we should not come here - elif decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: - fwrapper_cls = mem_fun_private_pv_wrapper_t - else: - if decl.overridable: - fwrapper_cls = mem_fun_v_wrapper_t - maker_cls = mem_fun_v_t - return ( maker_cls, fwrapper_cls ) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-14 06:19:18 UTC (rev 542) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-14 12:02:53 UTC (rev 543) @@ -4,6 +4,7 @@ # http://www.boost.org/LICENSE_1_0.txt) import types_database +import creators_wizard import class_organizer import call_policies_resolver from pygccxml import declarations @@ -566,7 +567,7 @@ if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) - maker_cls, fwrapper_cls = code_creators.guess_mem_fun_creator_classes( self.curr_decl ) + maker_cls, fwrapper_cls = creators_wizard.find_out_mem_fun_creator_classes( self.curr_decl ) maker = None fwrapper = None Added: pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py (rev 0) +++ pyplusplus_dev/pyplusplus/module_creator/creators_wizard.py 2006-09-14 12:02:53 UTC (rev 543) @@ -0,0 +1,61 @@ +# 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) + +"""this module defines few function that will guess what creator(s) should be +created for exposing a declaration +""" + +from pygccxml import declarations +from pyplusplus import code_creators + + +ACCESS_TYPES = declarations.ACCESS_TYPES +VIRTUALITY_TYPES = declarations.VIRTUALITY_TYPES + + +def find_out_mem_fun_creator_classes( decl ): + """return tuple of ( registration, declaration ) code creator classes""" + maker_cls = None + fwrapper_cls = None + access_level = decl.parent.find_out_member_access_type( decl ) + if access_level == ACCESS_TYPES.PUBLIC: + if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: + maker_cls = code_creators.mem_fun_t + elif decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: + fwrapper_cls = code_creators.mem_fun_pv_wrapper_t + maker_cls = code_creators.mem_fun_pv_t + else: + if decl.function_transformers: + fwrapper_cls = code_creators.mem_fun_v_transformed_wrapper_t + maker_cls = code_creators.mem_fun_v_transformed_t + else: + if decl.overridable: + fwrapper_cls = code_creators.mem_fun_v_wrapper_t + maker_cls = code_creators.mem_fun_v_t + elif access_level == ACCESS_TYPES.PROTECTED: + if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: + if decl.has_static: + fwrapper_cls = code_creators.mem_fun_protected_s_wrapper_t + maker_cls = code_creators.mem_fun_protected_s_t + else: + fwrapper_cls = code_creators.mem_fun_protected_wrapper_t + maker_cls = code_creators.mem_fun_protected_t + elif decl.virtuality == VIRTUALITY_TYPES.VIRTUAL: + if decl.overridable: + fwrapper_cls = code_creators.mem_fun_protected_v_wrapper_t + maker_cls = code_creators.mem_fun_protected_v_t + else: + fwrapper_cls = code_creators.mem_fun_protected_pv_wrapper_t + maker_cls = code_creators.mem_fun_protected_pv_t + else: #private + if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: + pass#in general we should not come here + elif decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: + fwrapper_cls = code_creators.mem_fun_private_pv_wrapper_t + else: + if decl.overridable: + fwrapper_cls = code_creators.mem_fun_v_wrapper_t + maker_cls = code_creators.mem_fun_v_t + return ( maker_cls, fwrapper_cls ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-14 06:19:30
|
Revision: 542 http://svn.sourceforge.net/pygccxml/?rev=542&view=rev Author: roman_yakovenko Date: 2006-09-13 23:19:18 -0700 (Wed, 13 Sep 2006) Log Message: ----------- fixing small bugs in file_writers. Bug was related to nested class associated declarations Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/unittests/algorithms_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-09-14 05:31:09 UTC (rev 541) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-09-14 06:19:18 UTC (rev 542) @@ -99,6 +99,18 @@ """ references to class declaration code creators. """ return self._associated_decl_creators + def recursive_associated_decl_creators( self ): + """ references to all class declaration code creators. """ + associated_creators = self.associated_decl_creators[:] + + relevant_creators = filter( lambda creator: isinstance( creator, class_t ) + , algorithm.make_flatten( self.creators ) ) + + map( lambda creator: associated_creators.extend( creator.associated_decl_creators ) + , relevant_creators ) + + return associated_creators + def _get_held_type(self): return self.declaration.held_type def _set_held_type(self, held_type): Modified: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-09-14 05:31:09 UTC (rev 541) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-09-14 06:19:18 UTC (rev 542) @@ -72,7 +72,7 @@ header_file = os.path.join( self.directory_path, self.wrapper_header(class_creator) ) self.write_file( header_file, wrapper_code ) - def split_internal_creators( self, class_creator, creators, pattern ): + def split_internal_creators( self, class_creator, creators, pattern, decl_creators=None): file_path = os.path.join( self.directory_path , self.create_base_fname( class_creator, pattern ) ) @@ -104,6 +104,12 @@ source_code.append( '' ) source_code.append( self.create_namespaces_code( creators ) ) + if decl_creators: + for decl_creator in decl_creators: + source_code.append( '' ) + source_code.append( decl_creator.create() ) + decl_creator.create = lambda: '' + # Write the register() function... source_code.append( '' ) source_code.append( '%s{' % function_decl ) @@ -175,7 +181,14 @@ def split_internal_classes( self, class_creator ): class_types = ( code_creators.class_t, code_creators.class_declaration_t ) creators = filter( lambda x: isinstance(x, class_types ), class_creator.creators ) - self.split_internal_creators( class_creator, creators, 'classes' ) + + decl_creators = [] + for creator in creators: + if not isinstance( creator, code_creators.class_t ): + continue + decl_creators.extend( creator.recursive_associated_decl_creators() ) + + self.split_internal_creators( class_creator, creators, 'classes', decl_creators ) return 'classes' def split_internal_member_variables( self, class_creator ): Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-14 05:31:09 UTC (rev 541) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-14 06:19:18 UTC (rev 542) @@ -199,7 +199,7 @@ class_wrapper = None decl_creators = [] if isinstance( class_creator, code_creators.class_t ): - decl_creators.extend( class_creator.associated_decl_creators ) + decl_creators.extend( class_creator.recursive_associated_decl_creators() ) if class_creator.wrapper: class_wrapper = class_creator.wrapper decl_creators.append( class_creator.wrapper ) Modified: pyplusplus_dev/unittests/algorithms_tester.py =================================================================== --- pyplusplus_dev/unittests/algorithms_tester.py 2006-09-14 05:31:09 UTC (rev 541) +++ pyplusplus_dev/unittests/algorithms_tester.py 2006-09-14 06:19:18 UTC (rev 542) @@ -121,22 +121,59 @@ minus_minus = xxx.operator( symbol='--' ) self.failUnless( 1 == len( minus_minus.readme() ), os.linesep.join( minus_minus.readme() ) ) +class multiple_files_tester_t(unittest.TestCase): + CLASS_DEF = \ + """ + namespace tester{ + struct b{ + enum EColor{ red, blue }; + enum EFruit{ apple, orange }; + + b(){} + b( int ){} + + void do_nothing(){} + + int do_somghing(){ return 1; } + + int m_dummy; + + struct b_nested{}; + }; + } + """ + def test(self): + mb = module_builder.module_builder_t( + [ module_builder.create_text_fc( self.CLASS_DEF ) ] + , gccxml_path=autoconfig.gccxml.executable ) + mb.namespace( name='::tester' ).include() + b = mb.class_( 'b' ) + b.add_declaration_code( '//hello world' ) + nested = b.class_( 'b_nested' ) + nested.add_declaration_code( '//hello nested decl' ) + nested.add_registration_code( '//hello nested reg', False ) + + mb.build_code_creator('b_multi') + mb.split_module( autoconfig.build_dir, on_unused_file_found=lambda fpath: fpath ) + class class_multiple_files_tester_t(unittest.TestCase): CLASS_DEF = \ """ namespace tester{ - struct X{ + struct x{ enum EColor{ red, blue }; enum EFruit{ apple, orange }; - X(){} - X( int ){} + x(){} + x( int ){} void do_nothing(){} int do_somghing(){ return 1; } int m_dummy; + + struct x_nested{}; }; } """ @@ -145,11 +182,16 @@ [ module_builder.create_text_fc( self.CLASS_DEF ) ] , gccxml_path=autoconfig.gccxml.executable ) mb.namespace( name='::tester' ).include() - X = mb.class_( 'X' ) - X.add_declaration_code( '//hello world' ) - mb.build_code_creator('dummy') + x = mb.class_( 'x' ) + x.add_registration_code( '//hello world reg' ) + x.add_declaration_code( '//hello world decl' ) + nested = x.class_( 'x_nested' ) + nested.add_declaration_code( '//hello nested decl' ) + nested.add_registration_code( '//hello nested reg', False ) + + mb.build_code_creator('x_class_multi') mb.split_module( autoconfig.build_dir - , [ mb.class_( '::tester::X' ) ] + , [ mb.class_( '::tester::x' ) ] , on_unused_file_found=lambda fpath: fpath ) @@ -169,6 +211,8 @@ def create_suite(): suite = unittest.TestSuite() + multiple_files_tester_t + suite.addTest( unittest.makeSuite(multiple_files_tester_t)) suite.addTest( unittest.makeSuite(doc_extractor_tester_t)) suite.addTest( unittest.makeSuite(class_organizer_tester_t)) suite.addTest( unittest.makeSuite(indent_tester_t)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-14 05:31:19
|
Revision: 541 http://svn.sourceforge.net/pygccxml/?rev=541&view=rev Author: roman_yakovenko Date: 2006-09-13 22:31:09 -0700 (Wed, 13 Sep 2006) Log Message: ----------- fixing include guards to be according to standard Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-14 05:23:14 UTC (rev 540) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-14 05:31:09 UTC (rev 541) @@ -75,12 +75,12 @@ @rtype: str """ tmpl = os.linesep.join([ - "#ifndef __%(file_name)s_hpp__pyplusplus_wrapper__" - , "#define __%(file_name)s_hpp__pyplusplus_wrapper__" + "#ifndef %(file_name)s_hpp__pyplusplus_wrapper" + , "#define %(file_name)s_hpp__pyplusplus_wrapper" , '' , "%(code)s" , '' - , "#endif//__%(file_name)s_hpp__pyplusplus_wrapper__" ]) + , "#endif//%(file_name)s_hpp__pyplusplus_wrapper" ]) content = '' if self.extmodule.license: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |