Revision: 1421
http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1421&view=rev
Author: roman_yakovenko
Date: 2008-10-05 13:19:47 +0000 (Sun, 05 Oct 2008)
Log Message:
-----------
refactoring call_policies.rest
Added Paths:
-----------
pyplusplus_dev/docs/documentation/functions/call_policies/
pyplusplus_dev/docs/documentation/functions/call_policies/as_tuple.rest
pyplusplus_dev/docs/documentation/functions/call_policies/call_policies.rest
pyplusplus_dev/docs/documentation/functions/call_policies/custom_call_policies.rest
pyplusplus_dev/docs/documentation/functions/call_policies/return_addressof.rest
pyplusplus_dev/docs/documentation/functions/call_policies/return_pointee_value.rest
pyplusplus_dev/docs/documentation/functions/call_policies/return_range.rest
pyplusplus_dev/docs/documentation/functions/call_policies/www_configuration.py
Removed Paths:
-------------
pyplusplus_dev/docs/documentation/functions/call_policies.rest
Added: pyplusplus_dev/docs/documentation/functions/call_policies/as_tuple.rest
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies/as_tuple.rest (rev 0)
+++ pyplusplus_dev/docs/documentation/functions/call_policies/as_tuple.rest 2008-10-05 13:19:47 UTC (rev 1421)
@@ -0,0 +1,87 @@
+========
+as_tuple
+========
+
+.. contents:: Table of contents
+
+----------
+Definition
+----------
+
+Class ``as_tuple`` is a model of `ResultConverterGenerator`_ which
+can be used to wrap C++ functions returning a pointer to arrays with fixed size.
+The policy will construct a Python tuple from the array and handle the array memory.
+
+-------
+Example
+-------
+
+.. code-block:: C++
+
+ struct vector3{
+ ...
+
+ float* clone_raw_data() const{
+ float* values = new float[3];
+ //copy values
+ return values;
+ }
+
+ const flow* get_raw_data() const{
+ return m_values;
+ }
+
+ private:
+ float m_values[3];
+ };
+
+ namespace bpl = boost::python;
+ namespace pypp_cp = pyplusplus::call_policies;
+ BOOST_PYTHON_MODULE(my_module){
+ bpl::class_< vector3 >( "vector3" )
+ .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_raw_data"
+ , &::vector3::get_raw_data
+ , bpl::return_value_policy< pypp_cp::arrays::as_tuple< 3, pypp_cp::memory_managers::none > >() ) );
+ }
+
+------------------
+``as_tuple`` class
+------------------
+
+``as_tuple`` is a template class that takes few arguments:
+
+1. the array size - compile time constant
+
+2. memory management policy - a class, which will manage the return value.
+ There are two built-in memory managers:
+
+ * delete\_ - the array will be deleted after it was copied to tuple, using
+ ``operator delete[]``
+
+ * none - do nothing
+
+The `Py++`_ code is slightly different from the C++ one, but it is definitely shorter:
+
+.. code-block:: Python
+
+ from pyplusplus import module_builder
+ from pyplusplus.module_builder import call_policies
+
+ mb = module_builder.module_builder_t( ... )
+ mb.member_function( 'clone_raw_data' ).call_policies \
+ = call_policies.convert_array_to_tuple( 3, call_policies.memory_managers.delete_ )
+ mb.member_function( 'get_raw_data' ).call_policies \
+ = call_policies.convert_array_to_tuple( 3, call_policies.memory_managers.none )
+
+
+.. _`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
+.. _`Python`: http://www.python.org
+.. _`GCC-XML`: http://www.gccxml.org
+
Added: pyplusplus_dev/docs/documentation/functions/call_policies/call_policies.rest
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies/call_policies.rest (rev 0)
+++ pyplusplus_dev/docs/documentation/functions/call_policies/call_policies.rest 2008-10-05 13:19:47 UTC (rev 1421)
@@ -0,0 +1,202 @@
+=============
+Call policies
+=============
+
+.. contents:: Table of contents
+
+------------
+Introduction
+------------
+
+`Boost.Python`_ has a `nice introduction`__ to call policies. `"Call policies concept"`_
+document will provide you with formal definition.
+
+.. __ : http://boost.org/libs/python/doc/tutorial/doc/html/python/functions.html#python.call_policies
+.. _`"Call policies concept"` : http://boost.org/libs/python/doc/v2/CallPolicies.html#CallPolicies-concept
+
+------
+Syntax
+------
+
+The call policies in `Py++`_ are named exactly as in `Boost.Python`_, only the
+syntax is slightly different. For instance, this call policy:
+
+.. code-block:: C++
+
+ return_internal_reference< 1, with_custodian_and_ward<1, 2> >()
+
+becomes in `Py++`_
+
+.. code-block:: Python
+
+ return_internal_reference( 1, with_custodian_and_ward(1, 2) )
+
+`Py++`_ supports all call policies presented in `Boost.Python`_.
+
+-------------
+Usage example
+-------------
+
+Every "callable" object in `Py++`_ has ``call_policies`` property.
+
+C++ code:
+
+ .. code-block:: C++
+
+ struct data{...};
+ const data& do_smth( const data& d, int x );
+
+ void return_second_arg( int x, int y );
+
+ typedef struct opaque_ *opaque_pointer;
+ opaque_pointer get_opaque();
+
+Python code:
+
+ .. code-block:: Python
+
+ from pyplusplus import module_builder
+ from pyplusplus.module_builder import call_policies
+
+ mb = module_builder.module_builder_t( ... )
+ mb.free_function( 'return_second_arg' ).call_policies = call_policies.return_arg( 2 )
+ #---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ mb.member_function( 'do_smth' ).call_policies = call_policies.return_self()
+ #-------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ mb.calldef( 'get_opaque' ).call_policies
+ = call_policies.return_value_policy( call_policies.return_opaque_pointer )
+
+--------
+Defaults
+--------
+
+`Py++`_ is able to "guess" few call policies, base on analysis of return type
+and\\or callable name:
+
+* ``default_call_policies``:
+
+ * `Python`_ immutable type returned by value: C++ fundamental types, ``std::string``, enumerations
+
+ * user-defined type ( class ) returned by value
+
+ * return type is ``const char*``
+
+* ``return_value_policy``
+
+ * ``return_opaque_pointer``
+
+ * return type is ``void*``
+
+ * return type is ``const void*``
+
+ * return type is ``T*`` and ``T`` is a user defined opaque type
+
+ ``class_t`` and ``class_declaration_t`` classes have ``opaque`` property.
+ You have to set it to ``True``, if you want `Py++`_ to create this call
+ policy automatically for all functions, that use ``T*`` as return type.
+
+ * ``copy_const_reference``
+
+ * return type is ``const T&``
+
+ * for member ``operator[]`` that returns const reference to immutable type
+
+ * ``return_by_value``
+
+ * return type is ``const wchar_t*``
+
+ * ``copy_non_const_reference``
+
+ * return type is ``T&``, for member ``operator[]`` that returns reference to immutable type
+
+ * ``return_internal_reference``
+
+ * return type is ``T&``, for member ``operator[]``
+
+* ``return_self``
+
+ This call policy will be used for ``operator=``.
+
+---------------------
+Missing call policies
+---------------------
+
+If you don't specify call policy for a function and it needs one, few things will
+happen:
+
+* `Py++`_ prints a warning message
+
+* `Py++`_ generates code with
+
+ .. code-block:: C++
+
+ /* undefined call policies */
+
+ comment, instead of call policy. If `Py++`_ was wrong and function doesn't
+ need call policy the generate code will compile fine, otherwise you will get a
+ compilation error.
+
+
+------------
+Special case
+------------
+
+Before you read this paragraph consider to read `Boost.Python`_ `return_opaque_pointer documentation`_.
+
+``return_value_policy( return_opaque_pointer )`` is a special policy for `Boost.Python`_.
+In this case, it requires from you to define specialization for the
+``boost::python::type_id`` function on the type pointed to by returned pointer.
+`Py++`_ will generate the required code.
+
+
+Actually you should define ``boost::python::type_id`` specialization also in case
+a function takes the opaque type as an argument. `Py++`_ can do it for you, all
+you need is to mark a declaration as opaque.
+
+Example:
+
+.. code-block:: C++
+
+ struct identity_impl_t{};
+ typedef identity_impl_t* identity;
+
+ struct world_t{
+
+ world_t( identity id );
+
+ identity get_id() const;
+
+ ...
+ };
+
+`Py++`_ code:
+
+.. code-block:: Python
+
+ mb = module_builder_t(...)
+ mb.class_( 'identity_impl_t' ).opaque = True
+
+
+.. _`return_opaque_pointer documentation` : http://boost.org/libs/python/doc/v2/return_opaque_pointer.html
+
+--------------------------
+Py++ defined call policies
+--------------------------
+
+`Py++`_ defines few call policies. I hope you will find them useful. I don't mind
+to contribute them to `Boost.Python`_ library, but I don't have enough free time
+to "boostify" them.
+
+.. _`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
+.. _`Python`: http://www.python.org
+.. _`GCC-XML`: http://www.gccxml.org
+
Added: pyplusplus_dev/docs/documentation/functions/call_policies/custom_call_policies.rest
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies/custom_call_policies.rest (rev 0)
+++ pyplusplus_dev/docs/documentation/functions/call_policies/custom_call_policies.rest 2008-10-05 13:19:47 UTC (rev 1421)
@@ -0,0 +1,39 @@
+====================
+custom_call_policies
+====================
+
+.. contents:: Table of contents
+
+----------
+Definition
+----------
+
+``custom_call_policies`` is a special call policy, which allows you to integrate
+the call policies, you defined, with `Py++`_
+
+-------
+Example
+-------
+
+.. code-block:: Python
+
+ from pyplusplus import module_builder
+ from pyplusplus.module_builder import call_policies
+
+ mb = module_builder.module_builder_t( ... )
+ mb.free_function( ... ).call_policies \
+ = call_policies.custom_call_policies( <<<your call policies code>>> )
+
+ Optionally you can specify name of the header file, which should be included:
+
+.. code-block:: Python
+
+ mb.free_function( ... ).call_policies \
+ = call_policies.custom_call_policies( <<<your call policies code>>>, "xyz.hpp" )
+
+
+.. _`Py++` : ./../../../pyplusplus.html
+.. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html
+.. _`Python`: http://www.python.org
+.. _`GCC-XML`: http://www.gccxml.org
+
Added: pyplusplus_dev/docs/documentation/functions/call_policies/return_addressof.rest
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies/return_addressof.rest (rev 0)
+++ pyplusplus_dev/docs/documentation/functions/call_policies/return_addressof.rest 2008-10-05 13:19:47 UTC (rev 1421)
@@ -0,0 +1,65 @@
+================
+return_addressof
+================
+
+.. contents:: Table of contents
+
+----------
+Definition
+----------
+
+Class ``return_addressof`` is a model of `ResultConverterGenerator`_ which
+can be used to wrap C++ functions returning any pointer, such that the pointer
+value is converted to ``unsigned int`` and it is copied into a new Python object.
+
+This call policy was created to be used with ``ctypes`` package and provide access
+to some raw\\low level data, without creating wrappers.
+
+Pay attention: you have to manage the memory by your own.
+
+-------
+Example
+-------
+
+.. code-block:: C++
+
+ int* get_value(){
+ static int buffer[] = { 0,1,2,3,4 };
+ return buffer;
+ }
+
+ namespace bpl = boost::python;
+ BOOST_PYTHON_MODULE(my_module){
+ def( "get_value"
+ , bpl::return_value_policy< pyplusplus::call_policies::return_addressof<> >() );
+ }
+
+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
+
+ mb = module_builder.module_builder_t( ... )
+ mb.free_function( return_type='float *' ).call_policies \
+ = call_policies.return_value_policy( call_policies.return_addressof )
+
+Python code:
+
+.. code-block:: Python
+
+ import ctypes
+ import my_module
+
+ buffer_type = ctypes.c_int * 5
+ buffer = buffer_type.from_address( my_module.get_value() )
+ assert [0,1,2,3,4] == list( buffer )
+
+.. _`ResultConverterGenerator` : http://boost.org/libs/python/doc/v2/ResultConverter.html#ResultConverterGenerator-concept
+
+.. _`Py++` : ./../../../pyplusplus.html
+.. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html
+.. _`Python`: http://www.python.org
+.. _`GCC-XML`: http://www.gccxml.org
+
Added: pyplusplus_dev/docs/documentation/functions/call_policies/return_pointee_value.rest
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies/return_pointee_value.rest (rev 0)
+++ pyplusplus_dev/docs/documentation/functions/call_policies/return_pointee_value.rest 2008-10-05 13:19:47 UTC (rev 1421)
@@ -0,0 +1,68 @@
+====================
+return_pointee_value
+====================
+
+.. contents:: Table of contents
+
+----------
+Definition
+----------
+
+Class ``return_pointee_value`` is a model of `ResultConverterGenerator`_ which
+can be used to wrap C++ functions returning any pointer, such that the pointee of
+return value is copied into a new Python object.
+
+-------
+Example
+-------
+
+.. code-block:: C++
+
+ float* get_value(){
+ static float value = 0.5;
+ return &value;
+ }
+
+ float* get_null_value(){
+ return (float*)( 0 );
+ }
+
+ namespace bpl = boost::python;
+ BOOST_PYTHON_MODULE(my_module){
+ def( "get_value"
+ , bpl::return_value_policy< pyplusplus::call_policies::return_pointee_value<> >() );
+
+ def( "get_null_value"
+ , bpl::return_value_policy< pyplusplus::call_policies::return_pointee_value<> >() );
+ }
+
+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
+
+ mb = module_builder.module_builder_t( ... )
+ mb.free_function( return_type='float *' ).call_policies \
+ = call_policies.return_value_policy( call_policies.return_pointee_value )
+
+Python code:
+
+.. code-block:: Python
+
+ import my_module
+
+ assert 0.5 == my_module.get_value()
+ assert None is my_module.get_null_value()
+
+
+
+.. _`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
+.. _`Python`: http://www.python.org
+.. _`GCC-XML`: http://www.gccxml.org
+
Added: pyplusplus_dev/docs/documentation/functions/call_policies/return_range.rest
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies/return_range.rest (rev 0)
+++ pyplusplus_dev/docs/documentation/functions/call_policies/return_range.rest 2008-10-05 13:19:47 UTC (rev 1421)
@@ -0,0 +1,233 @@
+=============
+return_range
+=============
+
+.. contents:: Table of contents
+
+----------
+Definition
+----------
+
+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`` class
+----------------------
+
+.. 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 our case we have to pass
+the following information:
+
+* the array size
+
+* the array type
+
+* "__getitem__" call policies for the 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 the following 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, the following 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];
+ }
+ ...
+ };
+
+The following "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
+.. _`Python`: http://www.python.org
+.. _`GCC-XML`: http://www.gccxml.org
+
Added: pyplusplus_dev/docs/documentation/functions/call_policies/www_configuration.py
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies/www_configuration.py (rev 0)
+++ pyplusplus_dev/docs/documentation/functions/call_policies/www_configuration.py 2008-10-05 13:19:47 UTC (rev 1421)
@@ -0,0 +1,6 @@
+name = 'call policies'
+#main_html_file = 'index.html'
+
+names = { 'call_policies' : 'call policies'
+}
+
Deleted: pyplusplus_dev/docs/documentation/functions/call_policies.rest
===================================================================
--- pyplusplus_dev/docs/documentation/functions/call_policies.rest 2008-10-05 12:35:30 UTC (rev 1420)
+++ pyplusplus_dev/docs/documentation/functions/call_policies.rest 2008-10-05 13:19:47 UTC (rev 1421)
@@ -1,606 +0,0 @@
-=============
-Call policies
-=============
-
-.. contents:: Table of contents
-
-------------
-Introduction
-------------
-
-`Boost.Python`_ has a `nice introduction`__ to call policies. `"Call policies concept"`_
-document will provide you with formal definition.
-
-.. __ : http://boost.org/libs/python/doc/tutorial/doc/html/python/functions.html#python.call_policies
-.. _`"Call policies concept"` : http://boost.org/libs/python/doc/v2/CallPolicies.html#CallPolicies-concept
-
-------
-Syntax
-------
-
-The call policies in `Py++`_ are named exactly as in `Boost.Python`_, only the
-syntax is slightly different. For instance, this call policy:
-
-.. code-block:: C++
-
- return_internal_reference< 1, with_custodian_and_ward<1, 2> >()
-
-becomes in `Py++`_
-
-.. code-block:: Python
-
- return_internal_reference( 1, with_custodian_and_ward(1, 2) )
-
-`Py++`_ supports all call policies presented in `Boost.Python`_.
-
--------------
-Usage example
--------------
-
-Every "callable" object in `Py++`_ has ``call_policies`` property.
-
-C++ code:
-
- .. code-block:: C++
-
- struct data{...};
- const data& do_smth( const data& d, int x );
-
- void return_second_arg( int x, int y );
-
- typedef struct opaque_ *opaque_pointer;
- opaque_pointer get_opaque();
-
-Python code:
-
- .. code-block:: Python
-
- from pyplusplus import module_builder
- from pyplusplus.module_builder import call_policies
-
- mb = module_builder.module_builder_t( ... )
- mb.free_function( 'return_second_arg' ).call_policies = call_policies.return_arg( 2 )
- #---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- mb.member_function( 'do_smth' ).call_policies = call_policies.return_self()
- #-------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- mb.calldef( 'get_opaque' ).call_policies
- = call_policies.return_value_policy( call_policies.return_opaque_pointer )
-
---------
-Defaults
---------
-
-`Py++`_ is able to "guess" few call policies, base on analysis of return type
-and\\or callable name:
-
-* ``default_call_policies``:
-
- * `Python`_ immutable type returned by value: C++ fundamental types, ``std::string``, enumerations
-
- * user-defined type ( class ) returned by value
-
- * return type is ``const char*``
-
-* ``return_value_policy``
-
- * ``return_opaque_pointer``
-
- * return type is ``void*``
-
- * return type is ``const void*``
-
- * return type is ``T*`` and ``T`` is a user defined opaque type
-
- ``class_t`` and ``class_declaration_t`` classes have ``opaque`` property.
- You have to set it to ``True``, if you want `Py++`_ to create this call
- policy automatically for all functions, that use ``T*`` as return type.
-
- * ``copy_const_reference``
-
- * return type is ``const T&``
-
- * for member ``operator[]`` that returns const reference to immutable type
-
- * ``return_by_value``
-
- * return type is ``const wchar_t*``
-
- * ``copy_non_const_reference``
-
- * return type is ``T&``, for member ``operator[]`` that returns reference to immutable type
-
- * ``return_internal_reference``
-
- * return type is ``T&``, for member ``operator[]``
-
-* ``return_self``
-
- This call policy will be used for ``operator=``.
-
----------------------
-Missing call policies
----------------------
-
-If you don't specify call policy for a function and it needs one, few things will
-happen:
-
-* `Py++`_ prints a warning message
-
-* `Py++`_ generates code with
-
- .. code-block:: C++
-
- /* undefined call policies */
-
- comment, instead of call policy. If `Py++`_ was wrong and function doesn't
- need call policy the generate code will compile fine, otherwise you will get a
- compilation error.
-
-
-------------
-Special case
-------------
-
-Before you read this paragraph consider to read `Boost.Python`_ `return_opaque_pointer documentation`_.
-
-``return_value_policy( return_opaque_pointer )`` is a special policy for `Boost.Python`_.
-In this case, it requires from you to define specialization for the
-``boost::python::type_id`` function on the type pointed to by returned pointer.
-`Py++`_ will generate the required code.
-
-
-Actually you should define ``boost::python::type_id`` specialization also in case
-a function takes the opaque type as an argument. `Py++`_ can do it for you, all
-you need is to mark a declaration as opaque.
-
-Example:
-
-.. code-block:: C++
-
- struct identity_impl_t{};
- typedef identity_impl_t* identity;
-
- struct world_t{
-
- world_t( identity id );
-
- identity get_id() const;
-
- ...
- };
-
-`Py++`_ code:
-
-.. code-block:: Python
-
- mb = module_builder_t(...)
- mb.class_( 'identity_impl_t' ).opaque = True
-
-
-.. _`return_opaque_pointer documentation` : http://boost.org/libs/python/doc/v2/return_opaque_pointer.html
-
---------------------------
-Py++ defined call policies
---------------------------
-
-custom_call_policies
---------------------
-
-``custom_call_policies`` policies functionality was born to allow you to define
-your own call polices and use them with same level of convenience as built-in ones.
-
-The usage is pretty simple:
-
-.. code-block:: Python
-
- from pyplusplus import module_builder
- from pyplusplus.module_builder import call_policies
-
- mb = module_builder.module_builder_t( ... )
- mb.free_function( ... ).call_policies \
- = call_policies.custom_call_policies( <<<your call policies code>>> )
-
- Optionally you can specify name of the header file, which should be included:
-
-.. code-block:: Python
-
- mb.free_function( ... ).call_policies \
- = call_policies.custom_call_policies( <<<your call policies code>>>, "xyz.hpp" )
-
-return_addressof
-----------------
-
-Class ``return_addressof`` is a model of `ResultConverterGenerator`_ which
-can be used to wrap C++ functions returning any pointer, such that the pointer
-value is converted to ``unsigned int`` and it is copied into a new Python object.
-
-This call policy was created to be used with ``ctypes`` package and provide access
-to some raw\\low level data, without creating wrappers.
-
-Pay attention: you have to manage the memory by your own.
-
-Example
-~~~~~~~
-
-.. code-block:: C++
-
- int* get_value(){
- static int buffer[] = { 0,1,2,3,4 };
- return buffer;
- }
-
- namespace bpl = boost::python;
- BOOST_PYTHON_MODULE(my_module){
- def( "get_value"
- , bpl::return_value_policy< pyplusplus::call_policies::return_addressof<> >() );
- }
-
-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
-
- mb = module_builder.module_builder_t( ... )
- mb.free_function( return_type='float *' ).call_policies \
- = call_policies.return_value_policy( call_policies.return_addressof )
-
-Python code:
-
-.. code-block:: Python
-
- import ctypes
- import my_module
-
- buffer_type = ctypes.c_int * 5
- buffer = buffer_type.from_address( my_module.get_value() )
- assert [0,1,2,3,4] == list( buffer )
-
-
-return_pointee_value
---------------------
-
-Class ``return_pointee_value`` is a model of `ResultConverterGenerator`_ which
-can be used to wrap C++ functions returning any pointer, such that the pointee of
-return value is copied into a new Python object.
-
-Example
-~~~~~~~
-
-.. code-block:: C++
-
- float* get_value(){
- static float value = 0.5;
- return &value;
- }
-
- float* get_null_value(){
- return (float*)( 0 );
- }
-
- namespace bpl = boost::python;
- BOOST_PYTHON_MODULE(my_module){
- def( "get_value"
- , bpl::return_value_policy< pyplusplus::call_policies::return_pointee_value<> >() );
-
- def( "get_null_value"
- , bpl::return_value_policy< pyplusplus::call_policies::return_pointee_value<> >() );
- }
-
-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
-
- mb = module_builder.module_builder_t( ... )
- mb.free_function( return_type='float *' ).call_policies \
- = call_policies.return_value_policy( call_policies.return_pointee_value )
-
-Python code:
-
-.. code-block:: Python
-
- import my_module
-
- assert 0.5 == my_module.get_value()
- assert None is my_module.get_null_value()
-
-as_tuple
---------
-
-Class ``as_tuple`` is a model of `ResultConverterGenerator`_ which
-can be used to wrap C++ functions returning a pointer to arrays with fixed size.
-The policy will construct a Python tuple from the array and treat the array memory.
-
-Example
-~~~~~~~
-
-.. code-block:: C++
-
- struct vector3{
- ...
-
- float* clone_raw_data() const{
- float* values = new float[3];
- //copy values
- return values;
- }
-
- const flow* get_raw_data() const{
- return m_values;
- }
-
- private:
- float m_values[3];
- };
-
- namespace bpl = boost::python;
- namespace pypp_cp = pyplusplus::call_policies;
- BOOST_PYTHON_MODULE(my_module){
- bpl::class_< vector3 >( "vector3" )
- .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_raw_data"
- , &::vector3::get_raw_data
- , bpl::return_value_policy< pypp_cp::arrays::as_tuple< 3, pypp_cp::memory_managers::none > >() ) );
- }
-
-``as_tuple`` class
-~~~~~~~~~~~~~~~~~~
-``as_tuple`` is a template class that takes few arguments:
-
-1. the size of the array - compile time constant
-
-2. memory management policy - a class, which will manage the return value.
- There are two built-in memory managers:
-
- * delete\_ - the array will be deleted after it was copied to tuple, using
- ``operator delete[]``
-
- * none - do nothing
-
-
-The `Py++`_ code is slightly different from the C++ one, but it is definitely shorter:
-
-.. code-block:: Python
-
- from pyplusplus import module_builder
- from pyplusplus.module_builder import call_policies
-
- mb = module_builder.module_builder_t( ... )
- mb.member_function( 'clone_raw_data' ).call_policies \
- = call_policies.convert_array_to_tuple( 3, call_policies.memory_managers.delete_ )
- 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
-dependency_libraries 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 the following 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, the following 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];
- }
- ...
- };
-
-The following "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
-.. _`Python`: http://www.python.org
-.. _`GCC-XML`: http://www.gccxml.org
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|