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: