FILE* and Boost.Python

One great feature of Boost.Python is the ability to write custom converters from Python types to C++ arguments. Most Boost.Python documentation, including the incredibly helpful post by misspent, show you how to write “rvalue” converters (e.g., pass-by-value or pass-by-const-reference).

However if you need to wrap a function which takes a FILE* argument the previous approach will not prove fruitful. But Boost.Python is clearly capable of handling a similar situation, namely the implicit conversion from a Python string type to a char* type. Since the conversion from the internal PyObject* to char* is likely to be done with the PyString_AsString function, I went off in search of that code.

There were no references in the installed headers, but it did appear in the source code in converter/builtin_converters.cpp in the convert_to_cstring() function:

// An lvalue conversion function which extracts a char const* from a
// Python String.
void* convert_to_cstring(PyObject* obj)
{
  return PyString_Check(obj) ? PyString_AsString(obj) : 0;
}

… which was later called as …

// Add an lvalue converter for char which gets us char const*
registry::insert
  (convert_to_cstring, type_id(),
   &converter::wrap_pytype<&PyString_Type>::get_pytype);

Jackpot! We should be able to mimic these lines to create a Python file to FILE* converter using PyFile_AsFile():

#include <boost/python.hpp>

namespace {
  void *convert_to_FILEptr(PyObject* obj) {
    return PyFile_Check(obj) ? PyFile_AsFile(obj) : 0;
  }
}

BOOST_PYTHON_MODULE(file_wrapper) {
  boost::python::converter::registry::insert
    (convert_to_FILEptr,
     boost::python::type_id<FILE>(),
     &boost::python::converter::wrap_pytype<&PyFile_Type>::get_pytype);
}

For a complete example including test code, see gist: 1265889.

Edit: Of course this also works with boost::python::extract<FILE*>. I’ve updated the gist to demonstrate the relevant usage.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s