=======================
Function transformation
=======================

.. contents:: Table of contents

------------
Introduction
------------

During the development of `Python`_ bindings for some C++ library, it might get 
necessary to write custom wrapper code for a particular function in order to 
make that function usable from `Python`_.

An often mentioned example that demonstrates the problem is the ``get_size()`` 
member function of a fictitious image class:

.. code-block:: C++

  void get_size(int& width, int& height);

This member function cannot be exposed with standard `Boost.Python`_ mechanisms.
The main reasons for this is that ``int`` is immutable type in `Python`_. 
An instance of immutable type could not be changed after construction. The only 
way to expose this function to `Python`_ is to create small wrapper, which will 
return a tuple. In `Python`_, the above function would instead be invoked like this:

.. code-block:: Python

  width, height = img.get_size()

and the wrapper could look like this:

.. code-block:: C++

  boost::python::tuple get_size( const image_t& img ){
      int width;
      int height;
      img.get_size( width, height );
      return boost::python::make_tuple( width, height );
  }
  
As you can see this function is simply invokes the original ``get_size()`` member 
function and return the output values as a tuple.

Unfortunately, C++ source code cannot describe the semantics of an argument so 
there is no way for a code generator tool such as `Py++`_ to know whether an 
argument that has a reference type is actually an output argument, an input 
argument or an input/output argument. That's why the user will always have to 
"enhance" the C++ code and tell the code generator tool about the missing 
information. 

Note: C++ fundamental types, enumerations and string are all mapped to `Python`_
immutable types.

Instead of forcing you to write the entire wrapper function, `Py++`_ allows you 
to provide the semantics of an argument(s) and then it will take care of 
producing the correct code:

.. code-block:: Python

   from pyplusplus import module_builder
   from pyplusplus import function_transformers as FT
   
   mb = module_builder.module_builder_t( ... )
   get_size = mb.mem_fun( 'image_t::get_size' )
   get_size.add_transformation( FT.output(0), FT.output(1) )
   #the following line has same effect
   get_size.add_transformation( FT.output('width'), FT.output('height') )

`Py++`_ will generate a code, very similar to one found in 
``boost::python::tuple get_size( const image_t& img )`` function.

---------
Thanks to 
---------

A thanks goes to Matthias Baas for his efforts and hard work. He did a research,
implemented the initial working version and wrote a lot of documentation. 

---------------------
Built-in transformers
---------------------

`Py++`_ comes with few predefined transformers:

* ``output``

* ``input``

* ``inout``

* ``modify_type``

* ``input_static_array``

* ``output_static_array``

* ``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.

I suggest you to start reading `output`_ transformer. It is pretty simple and
well explained.

.. _`output` : ./output.html

All built-in transformers could be applied on any function, except constructors
and pure virtual functions. The support for them be added in future releases.

You don't have to worry about call policies. You can set the call policy and
`Py++`_ will generate the correct code.

You don't have to worry about the number of arguments, transformers or return
value. `Py++`_ handles pretty well such use cases.


.. _`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

