Function transformation

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:

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:

width, height = img.get_size()

and the wrapper could look like this:

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:

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.

Transformers contents

Py++ comes with few predefined transformers:

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.

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.