Monday, June 30, 2008

boost::python examples

Continued from the previous post.

These are equivalent version of the examples on the previous post using boost::python.

[main2boost.cpp]


#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/object.hpp>

using namespace boost::python;

int main()
{
Py_Initialize();

object o_main = object(handle<>(borrowed(PyImport_AddModule("__main__"))));
object o_int10000(10000);
o_main.attr("tamtam") = o_int10000;
PyRun_SimpleString("print tamtam");

Py_Finalize();
return 0;
}


[main4boost.cpp]

#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/object.hpp>
#include <boost/python/dict.hpp>

using namespace boost::python;

int main()
{
Py_Initialize();

object o_main = object(handle<>(borrowed(PyImport_AddModule("__main__"))));
dict o_dict;
o_dict["foo"] = "bar";
o_main.attr("tamtam") = o_dict;

PyRun_SimpleString("print tamtam");

Py_Finalize();
return 0;
}


[main5boost.cpp]

#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/object.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/extract.hpp>
#include <iostream>
#include <string>

using namespace boost::python;

int main()
{
Py_Initialize();

PyRun_SimpleString("tamtam = {'foo':'bar'}");
object o_main = object(handle<>(borrowed(PyImport_AddModule("__main__"))));
dict o_dict(o_main.attr("tamtam"));
object o_value = o_dict["foo"];

//Oops I couldn't find a boost::python way of type checking.
if(PyObject_IsInstance(o_value.ptr(), (PyObject*)&PyString_Type))
{
std::string valstr = extract < std::string > (o_value);
std::cout << valstr << std::endl;
}

Py_Finalize();
return 0;
}


[main6boost.cpp]

#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/object.hpp>
#include <boost/python/extract.hpp>
#include <iostream>
#include <string>

using namespace boost::python;

int main()
{
Py_Initialize();

PyRun_SimpleString(
"def myfunc(a, b, c):¥n"
" print a¥n"
" return b + c¥n"
);

object o_main = object(handle<>(borrowed(PyImport_AddModule("__main__"))));

object o_func = o_main.attr("myfunc");

object o_int(10000);
object o_foo("foo");
object o_bar("bar");

object o_result = o_func(o_int, o_foo, o_bar);
//object o_result = o_func(10000, "foo", "bar"); also works.

std::string resultstr = extract < std::string > (o_result);
std::cout << resultstr << std::endl;

Py_Finalize();
return 0;
}


- o_ prefix is my naming convension

- To use Python C/API function directly, you need to include boost/python/detail/wrap_python.hpp instead of including Python.h. Include it before any other, just like Python.h

- borrowed() is used when you are passing a Python object that you are not responsible to dereference. That's all you need to be careful around reference counter, boost::python does everthing else.

- You'll find a better tut here.
http://www.boost.org/doc/libs/1_35_0/libs/python/doc/tutorial/doc/html/index.html
Document about "Exception handling" in the "Embedding" chapter is a must to read.

- Though I didn't used here, there's a function exec() that can replace PyRun_*().

No comments: