[C++-sig] Function handling with Boost

Christopher Schramm cschramm at shakaweb.org
Sun Jun 21 13:40:07 CEST 2009


Hi,

I'm new to Python's C API and developing my very first project using
Boost::Python (bpy). My goal is executing user defined scripts within an
embedded python environment using custom stdout and stderr and providing
a special built in module.

Beside a bunch of classes (which can be defined using bpy quite
comfortable) the module shall contain a couple of functions
and since bpy is apparently not primarily targeted at embedding and
doesn't provide a function type this is the point where all my problems
start.

My current solution is to get the global scope:

global = import("__main__").attr("__dict__");

And add my module using Py_InitModule3:

global["my_mod"] = object(handle<>(borrowed(Py_InitModule3("my_mod",
                                                functions, "docstr"))));

Adding classes and there methods is a nice, clear and easy task:

global["my_mod"].attr("__dict__")["myclass"] =
	class_<CPPClass, boost::noncopyable>("myclass", bpy::init<>())
                        .def("f1", &CPPClass::f1)
                        .def("f2", &CPPClass::f2);

But the functions need to be in the functions parameter of
Py_InitModule3, defined like:

PyMethodDef functions[] = {
    {"f1", &f1, METH_VARARGS, "my_doc"},
    {"f2", &f2, METH_VARARGS, "my_doc"},
    {0, 0}
};

And now the implementations have to be PyCFunction type, i. e. have the
signature PyObject* (PyObject*, PyObject*), not a (more or less)
arbitrary one they could have when used in bpy's def(). This means the
number of arguments given to the function within the python code could
be wrong, I need to convert from PyObject to bpy types to C++ types and
all the way back and there are traps like returning temporary pointers
or memory leaks.

An implementation could look like:

PyObject* f1(PyObject* self, PyObject* args)
{
    bpy::handle<> arg1, arg2;
    PyArg_UnpackTuple(args, "func", 1, 2, &arg1, &arg2);

    if (arg2.get()) {
        ...
    }
    ...
    ...bpy::extract<const char*>(bpy::object(arg1))...

    return Py_BuildValue("s", my_cstr_result);
}

Beside the problems already mentioned this means missing bpy features
for the functions like automatic docstrings, return value policies etc.

So I would really like to know whether there's a better way to do what
I'm doing. Especially a more boost like way ;-)

Thanks for any reply!
Christopher Schramm



More information about the Cplusplus-sig mailing list