[pygccxml-commit] SF.net SVN: pygccxml: [916]
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2007-02-20 11:04:53
|
Revision: 916 http://svn.sourceforge.net/pygccxml/?rev=916&view=rev Author: roman_yakovenko Date: 2007-02-20 03:04:51 -0800 (Tue, 20 Feb 2007) Log Message: ----------- updating documentation Modified Paths: -------------- pyplusplus_dev/docs/documentation/functions/call_policies.rest pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest pyplusplus_dev/unittests/call_policies_tester.py pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py website/site_creator/page_creator.py Modified: pyplusplus_dev/docs/documentation/functions/call_policies.rest =================================================================== --- pyplusplus_dev/docs/documentation/functions/call_policies.rest 2007-02-19 19:33:01 UTC (rev 915) +++ pyplusplus_dev/docs/documentation/functions/call_policies.rest 2007-02-20 11:04:51 UTC (rev 916) @@ -246,13 +246,13 @@ struct vector3{ ... - float* clone_row_data() const{ + float* clone_raw_data() const{ float* values = new float[3]; //copy values return values; } - const flow* get_row_data() const{ + const flow* get_raw_data() const{ return m_values; } @@ -264,11 +264,11 @@ namespace pypp_cp = pyplusplus::call_policies; BOOST_PYTHON_MODULE(my_module){ bpl::class_< vector3 >( "vector3" ) - .def( "clone_row_data" - , &::vector3::clone_row_data + .def( "clone_raw_data" + , &::vector3::clone_raw_data , bpl::return_value_policy< pypp_cp::arrays::as_tuple< 3, pypp_cp::memory_managers::delete_ > >() ) - .def( "get_row_data" - , &::vector3::get_row_data + .def( "get_raw_data" + , &::vector3::get_raw_data , bpl::return_value_policy< pypp_cp::arrays::as_tuple< 3, pypp_cp::memory_managers::none > >() ) ); } @@ -295,14 +295,230 @@ from pyplusplus.module_builder import call_policies mb = module_builder.module_builder_t( ... ) - mb.member_function( 'clone_row_data' ).call_policies \ + mb.member_function( 'clone_raw_data' ).call_policies \ = call_policies.convert_array_to_tuple( 3, call_policies.memory_managers.delete_ ) - mb.member_function( 'get_row_data' ).call_policies \ + mb.member_function( 'get_raw_data' ).call_policies \ = call_policies.convert_array_to_tuple( 3, call_policies.memory_managers.none ) +return_range +------------ +Class ``return_range`` is a model of `CallPolicies`_, which can be used to wrap +C++ functions that return a pointer to some array. The new call policy constructs +object, which provides a regular `Python`_ `sequence`_ interface. +.. _`sequence` : http://docs.python.org/lib/typesseq.html + + +Example +~~~~~~~ + +.. code-block:: C++ + + struct image_t{ + + ... + + const unsigned char* get_data() const{ + return m_raw_data; + } + + ssize_t get_width() const{ + return m_width; + } + + ssize_t get_height() const{ + return m_height; + } + + private: + unsigned long m_width; + unsigned long m_height; + unsigned char* m_raw_data; + }; + +Before introducing the whole solution, I would like to describe "return_range" +interface. + +``return_range`` definition +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: C++ + + template < typename TGetSize + , typename TValueType + , typename TValuePolicies=boost::python::default_call_policies > + struct return_range : boost::python::default_call_policies + { ... }; + +`Boost.Python`_ call policies are stateless classes, which do not care any +information about the invoked function or object. In out case we have to pass +next information: + +* the size of array + +* array type + +* "__getitem__" call policies for array elements + + +``TGetSize`` parameter +++++++++++++++++++++++ + +``TGetSize`` is a class, which is responsible to find out the size of the returned +array. + +``TGetSize`` class must have: + +* default constructor + +* call operator with next signature: + + .. code-block:: C++ + + ssize_t operator()( boost::python::tuple args ); + + ``args`` is a tuple of arguments, the function was called with. + + Pay attention: this operator will be invoked **after** the function. This + call policy is **not thread-safe**! + +For our case, next class could be defined: + +.. code-block:: C++ + + struct image_data_size_t{ + ssize_t operator()( boost::python::tuple args ){ + namespace bpl = boost::python; + bpl::object self = args[0]; + image_t& img = bpl::extract< image_t& >( self ); + return img.get_width() * img.get_height(); + } + }; + +Passing all arguments, instead of single "self" argument gives you an ability +to treat functions, where the user asked to get access to the part of the array. + +.. code-block:: C++ + + struct image_t{ + ... + const unsigned char* get_data(ssize_t offset) const{ + //check that offset represents a legal value + ... + return &m_raw_data[offset]; + } + ... + }; + +Next "get size" class treats this situation: + +.. code-block:: C++ + + struct image_data_size_t{ + ssize_t operator()( boost::python::tuple args ){ + namespace bpl = boost::python; + bpl::object self = args[0]; + image_t& img = bpl::extract< image_t& >( self ); + bpl::object offset_obj = args[1]; + ssize_t offset = bpl::extract< ssize_t >( offset_obj ); + return img.get_width() * img.get_height() - offset; + } + }; + + +``TValueType`` parameter +++++++++++++++++++++++++ + +``TValueType`` is a type of array element. In our case it is ``unsigned char``. + +``TValuePolicies`` parameter +++++++++++++++++++++++++++++ + +``TValuePolicies`` is a "call policy" class, which will be applied when the array +element is returned to `Python`_. This is a call policy for "__getitem__" function. + +``unsigned char`` is mapped to immutable type in `Python`_, so I have to use +``default_call_policies``. ``default_call_policies`` is a default value for +``TValuePolicies`` parameter. + + +I think, now you are ready to see the whole solution: + +.. code-block:: C++ + + namespace bpl = boost::python; + namespace ppc = pyplusplus::call_policies; + + BOOST_PYTHON_MODULE(my_module){ + bpl::class_< image_t >( "image_t" ) + .def( "get_width", &image_t::get_width ) + .def( "get_height", &image_t::get_height ) + .def( "get_raw_data", ppc::return_range< image_size_t, unsigned char >() ); + } + +Py++ integration +~~~~~~~~~~~~~~~~ + +The `Py++`_ code is not that different from what you already know: + +.. code-block:: Python + + from pyplusplus import module_builder + from pyplusplus.module_builder import call_policies + + image_size_code = \ + """ + struct image_data_size_t{ + ssize_t operator()( boost::python::tuple args ){ + namespace bpl = boost::python; + bpl::object self = args[0]; + image_t& img = bpl::extract< image_t& >( self ); + return img.get_width() * img.get_height(); + } + }; + """ + + mb = module_builder.module_builder_t( ... ) + image = mb.class_( 'image_t' ) + image.add_declaration_code( image_size_code ) + get_raw_data = image.mem_fun( 'get_raw_data' ) + get_raw_data.call_policies \ + = call_policies.return_range( get_raw_data, "image_data_size_t" ) + +call_policies.return_range arguments: + +1. A reference to function. `Py++`_ will extract by itself the type of the array + element. + +2. A name of "get size" class. + +3. A call policies for "__getitem__" function. `Py++`_ will analyze the array + element type. If the type is mapped to immutable type, than ``default_call_policies`` + is used, otherwise you have to specify call policies. + + +Python usage code: + +.. code-block:: Python + + from my_module import * + + img = image_t(...) + for p in img.get_raw_data(): + print p + +Dependencies +~~~~~~~~~~~~ + +The new call policy depends on `new indexing suite`_ and `Py++`_ :-). But if you +want you can extract the relevant piece of code from `this file`_. + +.. _`new indexing suite` : ./../containers.html +.. _`this file` : http://pygccxml.svn.sourceforge.net/viewvc/pygccxml/pyplusplus_dev/pyplusplus/code_repository/call_policies.py?view=markup + .. _`ResultConverterGenerator` : http://boost.org/libs/python/doc/v2/ResultConverter.html#ResultConverterGenerator-concept +.. _`CallPolicies` : http://www.boost.org/libs/python/doc/v2/CallPolicies.html#CallPolicies-concept .. _`Py++` : ./../pyplusplus.html .. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html Modified: pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest =================================================================== --- pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest 2007-02-19 19:33:01 UTC (rev 915) +++ pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest 2007-02-20 11:04:51 UTC (rev 916) @@ -24,6 +24,8 @@ * ``input_c_buffer`` +* ``transfer_ownership`` + The set doesn't cover all common use cases, but it will grow with every new version of `Py++`_. If you created your own transformer consider to contribute it to the project. Modified: pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest =================================================================== --- pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest 2007-02-19 19:33:01 UTC (rev 915) +++ pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest 2007-02-20 11:04:51 UTC (rev 916) @@ -18,10 +18,11 @@ New in version grater than 0.8.5. -Known limits ------------- +Pay attention! +-------------- -Implicit conversion should exist between new type and the old one. +If implicit conversion between new type and the old one does not exist +"reinterpret_cast" will be used. ------- Example Modified: pyplusplus_dev/unittests/call_policies_tester.py =================================================================== --- pyplusplus_dev/unittests/call_policies_tester.py 2007-02-19 19:33:01 UTC (rev 915) +++ pyplusplus_dev/unittests/call_policies_tester.py 2007-02-20 11:04:51 UTC (rev 916) @@ -22,7 +22,8 @@ get_size_code = """ struct raw_data_size_t{ ssize_t - operator()( boost::python::object self ){ + operator()( boost::python::tuple args ){ + boost::python::object self = args[0]; call_policies::return_range_image_t& image = boost::python::extract<call_policies::return_range_image_t&>( self ); return image.raw_data.size(); Modified: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2007-02-19 19:33:01 UTC (rev 915) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2007-02-20 11:04:51 UTC (rev 916) @@ -231,20 +231,21 @@ }; -struct transfer_ownership_tester_t{ - struct resources_t{ - resources_t(){ - std::cout << "created"; - } - ~resources_t(){ - std::cout << "destroyed"; - } - }; - void tester(resources_t* r){ - delete r; + +} + +struct resource_t{ + resource_t(){ + std::cout << "created"; } + ~resource_t(){ + std::cout << "destroyed"; + } }; +void do_smth(resource_t* r){ + } + #endif//__function_transformations_to_be_exported_hpp__ Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2007-02-19 19:33:01 UTC (rev 915) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2007-02-20 11:04:51 UTC (rev 916) @@ -85,11 +85,10 @@ write_s = cls.mem_fun( 'write_s' ) write_s.add_transformation( ft.input_c_buffer( 'buffer', 'size' ) ) - resource = mb.class_( 'resources_t' ) + resource = mb.class_( 'resource_t' ) resource.held_type = 'std::auto_ptr< %s >' % resource.decl_string - transfer_ownership_tester = mb.class_( 'transfer_ownership_tester_t' ) - tester = transfer_ownership_tester.mem_fun( 'tester' ) - tester.add_transformation( ft.transfer_ownership( 0 ) ) + do_smth = mb.free_fun( 'do_smth' ) + do_smth.add_transformation( ft.transfer_ownership( 0 ) ) def run_tests(self, module): """Run the actual unit tests. Modified: website/site_creator/page_creator.py =================================================================== --- website/site_creator/page_creator.py 2007-02-19 19:33:01 UTC (rev 915) +++ website/site_creator/page_creator.py 2007-02-20 11:04:51 UTC (rev 916) @@ -42,15 +42,20 @@ language = options['language'] if content and 'source-file' in options: - error = state_machine.reporter.error( "You cannot both specify a source-file and include code directly.", - docutils.nodes.literal_block(block_text,block_text), line=lineno) + error = state_machine.reporter.error( "You cannot both specify a source-file and include code directly." + , docutils.nodes.literal_block(block_text,block_text), line=lineno) return [error] source_code = None if content: source_code = os.linesep.join( map( lambda s: s.rstrip(), content ) ) else: - source_code = file( options['source-file'] ).read() + try: + source_code = file( options['source-file'] ).read() + except Exception, err: + error = state_machine.reporter.error( "Exception: " + str( err ) + , docutils.nodes.literal_block(block_text,block_text), line=lineno) + return [error] html = pykleur.highlight( source_code , pykleur.lexers.get_lexer_by_name( language.lower() ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |