boost python and custom exception

6. July 2012 08:00

 

One of the problems faced with creating boost python wrappers is that sooner or later you can run into the situation where you need to support extra exception messages which are being thrown from C++ code but are not understood by python or the python wrapper. So this is a guide to support these extra exceptions.

 

You will know that you have come across this issue when you see the following being produced in python. In this case the Example function in C++ throws a MyException class which provides an error message which in its current state just isn't really useful to try to trace the problem.

 

 

>>> import MyClass_py
>>> obj = MyClass_py.MyClass()
>>> obj.Example()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: unidentifiable C++ exception
>>>

 

 

In previous posts about creating python wrappers and supporting operator overloading. I have been using much the same example code. In this case it has been changed to add the extra exception. So the C++ code now looks like this.

 

 

class MyException {
	public:
		MyException(const std::string str) {
			m_str = str;
		}
		
		~MyException() {
		
		}
		
		std::string GetMessage() const {
			return m_str;
		}
		
	private:
		std::string m_str;
};

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			throw(MyException("Hello World"));
		}
		
};

 

 

To get the exception method supported we need to add an exception converter to our python module using a boost python macro register_exception_translator and an extra C/C++ function in our wrapper. Note that the C++ function should not be in the BOOST_PYTHON_MODULE section but the register_exception_translator is. This is how it should look to handle the exception.

Also take note that because the MyExceptionTranslator requires the argument to be a const the functions that you call must also be marked as const or it will not compile. In this case the function for "MyException::GetMessage" must be declared as "std::string MyException::GetMessage() const" to say that it does not modify the contents of the MyException this is because it is meant to be constant.

 

static void MyExceptionTranslator(const MyException &err) {
        PyErr_SetString(PyExc_UserWarning, err.GetMessage().c_str());
}


BOOST_PYTHON_MODULE(MyClass_py)
{
	register_exception_translator<MyException>(&MyExceptionTranslator);

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		
	;
	
}

 

When compiled and run from python we now get the following instead of the useless error message above

 

 

>>> import MyClass_py
>>> obj = MyClass_py.MyClass()
>>> obj.Example()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UserWarning: Hello World

 

I have included a full working example.

 

#include <string>

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/init.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/overloads.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>

using namespace boost::python;


class MyException {
	public:
		MyException(const std::string str) {
			m_str = str;
		}
		
		~MyException() {
		
		}
		
		std::string GetMessage() const {
			return m_str;
		}
		
	private:
		std::string m_str;
};

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			throw(MyException("Hello World"));
		}
		
};

static void MyExceptionTranslator(const MyException &err) {
        PyErr_SetString(PyExc_UserWarning, err.GetMessage().c_str());
}


BOOST_PYTHON_MODULE(MyClass_py)
{
	register_exception_translator<MyException>(&MyExceptionTranslator);

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		
	;
	
}

The above example can be compiled with

 

g++ -shared -Wall MyClass_py.cpp -o MyClass_py.so -I/usr/include/python2.6/ -lboost_python -lpython2.6

 

E-mail Kick it! DZone it! del.icio.us Permalink


boost python operator overloading for calling C++ classes

3. July 2012 08:00

 

In a previous post about creating basic python wrappers. I mentioned that there can be an issue with trying to call C++ from the python wrapper which are operator overloaded. Taking the following C++ code the python wrapper cannot tell the different between the two functions when being compile or which one should be used.

 

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			return "Hello World";
		}
		
		std::string Example(std::string str) {
			return str;
		}
};

BOOST_PYTHON_MODULE(MyClass_py)
{

	class_( "MyClass", init<>() )
	
		.def("Example", &MyClass::Example)
		
	;
	
}

When compiling you will get en error of this.

 

MyClass_py.cpp: In function 'void init_module_MyClass_py()':
MyClass_py.cpp:44: error: no matching function for call to 'boost::python::class_<MyClass, boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::def(const char [8], <unresolved overloaded function type>)'

 

You can work around it using the static cast to get the correct function to be called and rename the python function to something else. Effectivly this removes the operating overload from the python end of things when it is not supported. The example of the wrapper code is below.

 

BOOST_PYTHON_MODULE(MyClass_py)
{

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		.def("ExampleStr", static_cast< std::string (MyClass::*)(std::string ) > (&MyClass::Example) )
		
	;
	
}

Our python code is then forced to use the aliased function name.

 

>>> import MyClass_py
>>> obj = MyClass_py.MyClass()
>>> obj.Example()
'Hello World'
>>> obj.ExampleStr('Foo')
'Foo'
>>>

I have included an complete example for you to play with.

 

#include <string>

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/init.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/overloads.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>

using namespace boost::python;

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			return "Hello World";
		}
		
		std::string Example(std::string str) {
			return str;
		}
};


BOOST_PYTHON_MODULE(MyClass_py)
{

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", static_cast< std::string (MyClass::*)() > (&MyClass::Example) )
		.def("ExampleStr", static_cast< std::string (MyClass::*)(std::string ) > (&MyClass::Example) )
		
	;
	
}

 

You can compile the above with

 

g++ -shared -Wall MyClass_py.cpp -o MyClass_py.so -I/usr/include/python2.6/ -lboost_python -lpython2.6

E-mail Kick it! DZone it! del.icio.us Permalink


Creating A basic python wrapper for C++ objects

30. June 2012 11:33

This short tutorial will show you how to get started creating a python wrapper using the boost python library to construct and call C++ functions from python. These are actually quite easy to create basic support for and can typically be created in a matter of minutes to give python support to your shared lib's. A typical use case where I have been using them is to wrap a C++ client lib in a C++ client / server application so that it can be used to display web pages in django.

 

Before you get started on the code you are going to need to get the boost python wrappers. In debian / ubuntu this should be easy just install the package 'libboost-python-dev' using apt-get.

 

Before we can produce a python wrapper we need something in C++ that we can call. So for this I am going to use the following basic example of a C++ class

 

 

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			return "Hello World";
		}
};

 

 

To create a basic python wrapper we will need the following C++ headers from the boost python wrappers.

 

 

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/init.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/overloads.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>

 

This will give us access to the correct macro's which will automatically generate the correct wrappers for us. We can declare our python module as 'MyClass_py' this of course means when we are compiling we will be creating a shared object 'MyClass_py.so' so that python can load it with 'import MyClass_py.so'

 

 

BOOST_PYTHON_MODULE(MyClass_py)
{

}

 

Anything that we wish to wrapp will be added inside the BOOST_PYTHON_MODULE above and wrapping classes is easy and example of being able to map the C++ to python is below that can be extended to take care of all the functions that you wish to support. You should also be aware that there is limited / no support in dealing with operator overloading in python wrappers however there are ways to deal with this issue and I will mention them in another tutorial.

 

 

BOOST_PYTHON_MODULE(MyClass_py)
{

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", &MyClass::Example)
		
	;
	
}

 

There is of course a matter of getting the code to compile which involves making a shared lib. The name of the shared lib is important it must match the name in the BOOST_PYTHON_MODULE or the module will not load into python.

 

 

g++ -shared -Wall MyClass_py.cpp -o MyClass_py.so -I/usr/include/python2.6/ -lboost_python -lpython2.6

 

There there is a matter of testing the above with python. Here is a simple example.

 

>>> import MyClass_py
>>> obj = MyClass_py.MyClass()
>>> obj.Example()
'Hello World'

 

Here is a full working example below that can be copied / pasted into a file.

 

 

#include <string>

#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/init.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/return_by_value.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/overloads.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>

using namespace boost::python;

class MyClass {
	public:
		MyClass() { }
		~MyClass() { }
		
		std::string Example() {
			return "Hello World";
		}
};


BOOST_PYTHON_MODULE(MyClass_py)
{

	class_<MyClass>( "MyClass", init<>() )
	
		.def("Example", &MyClass::Example)
		
	;
	
}

 

E-mail Kick it! DZone it! del.icio.us Permalink


Using gperf with C++

16. June 2012 00:02

 

Did you know that you can use gperf with C++ to generate hash tables which can be used to make code easyier to read and also run faster. This is a short guide on how to do this for something that is quite a common problem.

 

On of these simple problems comes down to code clarity and performance. If you have ever seen large functions that spam 1000's or line of if or case statements then you will know what the problem is already. Though typically this problem is formed in client / server driven software that is processing commands on the server. It is caused because the server needs to figure out what function to run from an incomming command from the client. Quite often this end's up in code something like this.

 

if (command == "ONE") { DoOne(); }
if (command == "TWO") { DoTwo(); }
if (command == "THREE") { DoThree(); }

 

 

Typically in a large client / server project the above can grow to 1000's of commands. Quite often new commands are always added to the end of the list. The obvious problem here is that for the 1000'th command it has to evaluate 1000 if statements. This obviously isn't a great solution.

 

So here is a better way to do it. We can start with some example code that might exist on the server. eg The functions that are being run as the incoming commands are being processed. This is of course a simple example.

 

 

class Test {
public:
    static void One() { printf("One\n"); }
    static void Two() { printf("Two\n"); }
    static void Three() { printf("Three\n"); }
};

 

We also need to create a method of calling this so that the functions above can be called at design time. We can do that by creating a structure with a name (eg the command) and a pointer to the function.

 


struct TType {
    const char *name;
    void (*func) (void);
};

 

The next idea is to create a function that can lookup the TType structure in a dataset by the incoming command name. This is where gperf comes in and we can create a gperf file which will end up looking something like the following. There is a working example of a gperf file at the end of this post. Something that is also worth pointing out that in the data list between the %% and %% lines you are not permitted to use spaces as these will be considered empty strings. After all they are valid data. However you can add spacing / comments by prefixing with the #

 

 

%ignore-case
%language=C++
%define lookup-function-name Lookup
%define class-name Functions
struct TType
%%
####
ONE,    Test::One
TWO,    Test::Two
THREE,  Test::Three
####
%%

 

The above will tell gperf to ignore case when doing the string matching and it will specifiy the output to be C++. It will also create a static C++ class and function in the generate output file named Functions::Lookup along with a static structure of the TType which also contains the entire data list. As an example the C++ code that is generated is as followed. However it does also create a number of other items releated to the gperf hash calculate that is performed during the lookup. I have only included a small chunk of the file below as the rest of it really isn't human readable.

 

 

static const struct TType wordlist[] =
  {
    {""}, {""}, {""},
#line 31 "gperf-exmaple.gperf"
    {"TWO",    Test::Two},
#line 30 "gperf-exmaple.gperf"
    {"ONE",    Test::One},
#line 32 "gperf-exmaple.gperf"
    {"THREE",  Test::Three}
  };

const struct TType *
Functions::Lookup (register const char *str, register unsigned int len)
{
  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
    {
      register int key = hash (str, len);

      if (key <= MAX_HASH_VALUE && key >= 0)
        {
          register const char *s = wordlist[key].name;

          if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strcmp (str, s))
            return &wordlist[key];
        }
    }
  return 0;
}
#line 34 "gperf-exmaple.gperf"

 

The next step in getting this to work is to make the program call the lookup function. This is normally done by creating the above file from the gperf file by running the gperf command like gperf -tCG gperf-example.gperf > gperf-example.h and then including the file into the C++ code where the lookup function will be called from. As an example you end up with a program that looks like this.

 

 

#include "gperf-example.h"


int main(int argc, char **argv) {
    const TType *tmp = Functions::Lookup("One", 3);

    if (tmp == NULL) {
        printf("FAILED\n");
    } else {
        tmp->func();
    }
}

 

The above is obviously a little easyier to maintain in the long run and runs a lot faster that trying to process 100's of if statements. It can also be integrated with the build system so that the file can be produced automatically when updates are made.

 

Here is a complete runnable example of a gperf configuration. I put this together to show how to the C++ code can be mixed into the gperf file.

 

 

%{

/* gperf -tCG gperf-exmaple.gperf > myfile.cpp */

#include <stdio.h>
#include <string.h>

struct TType {
    const char *name;
    void (*func) (void);
};


class Test {
public:
    static void One() { printf("One\n"); }
    static void Two() { printf("Two\n"); }
    static void Three() { printf("Three\n"); }
};

%}

%ignore-case
%language=C++
%define lookup-function-name Lookup
%define class-name Functions
struct TType
%%
####
ONE,    Test::One
TWO,    Test::Two
THREE,  Test::Three
####
%%


int main(int argc, char **argv) {
    const TType *tmp = Functions::Lookup("One", 3);

    if (tmp == NULL) {
        printf("FAILED\n");
    } else {
        tmp->func();
    }
}

 

The above can be processed, compile and run with the following commands.

 

 

gperf -tCG gperf-example.gperf > gperf-example.cpp
g++ -Wall gperf-example.cpp -o gperf-example
E-mail Kick it! DZone it! del.icio.us Permalink


C++ - Optional function arguments / parameters

10. May 2012 13:00

 

This is a quick tip in C++ for providing support for optional parameters on functions. This works because when a function is declared in C++ it can be given a default value and when that paramater is missing from the calling function the compiler will automatically add it during compile time and pass the default value.

 

Heres a simple example of this.

 

 

#include <stdio.h>

bool func(bool val = false) {
    return val;
}


int main(int argc, char **argv) {

    printf("%d\n", func());
    printf("%d\n", func(false));
    printf("%d\n", func(true));

    return 0;
}

 

E-mail Kick it! DZone it! del.icio.us Permalink