logo       

Re: instantiating python objects within C++: msg#00286

python.c++

Subject: Re: instantiating python objects within C++

David Abrahams wrote:
thor.arne.johansen@xxxxxxx writes:


http://mail.python.org/pipermail/c++-sig/2002-December/002833.html

I never got any feedback on this posting, so I don't know how 'good'
the example is, but it seems to work allright.


Oh, I'm sorry you didn't get any feedback. Dirk, do you have
anything to say about this one?


I remember seeing that post. But I didn't really know what to say about it then. Now that I've had more experience myself, I'll give it another whirl. :)

Well, with Boost.Python in its current form, this example is pretty good. I do have a some comments on stylistic C++ issues (#defines, printf, etc) but I assume that's not the kind of feedback you were hoping for. For the rest, I only have a few things to say:


Firstly, your use of PythonException seems unnecessary to me. Perhaps you didn't know, but Boost.Python already throws a C++ exception when a Python exception occurs (in most cases). You can find more info, and an example, in the tutorial: (URL might need some assembling)
http://boost.org/libs/python/doc/tutorial/doc/using_the_interpreter.html#exception_handling

In particular, you could write your import_module as this:

boost::python::handle<>
import_module(std::string const& module_name)
{
return handle<>(
PyImport_ImportModule(const_cast<char*>(module_name.c_str()) );
}

If PyImport_ImportModule fails, it returns 0, as you already know. The pointer passed to handle<>'s constructor will therefore be 0 as well. In turn, this will make it throw a boost::python::error_already_set exception. You can then catch this and use PyErr_Print, PyErr_Fetch (possible wrapped in a convenience function) or whatever.


Secondly, you can make the code clearer (and safer) by using handle<> and object where you currently use instead PyObject* and PY_XDECREF. Again, the details are in the tutorial: (URL might need some assembling) http://boost.org/libs/python/doc/tutorial/doc/using_the_interpreter.html#reference_counting_handles

For instance, your get_function would become:

boost::python::object
get_function(char const* func_name)
{
using namespace boost::python;
dict d(handle<>(PyModule_GetDict(module.get()));
return d[func_name];
}

I hope you can imagine what it would do to a more complex piece of code, like the code from getExceptionDetail that you adapted.


Note that I didn't test any of the above code. I apologize if it doesn't quite work, but I hope you get the idea.


Lastly, I'd like to say that I've made a little class to be added to Boost.Python which would make this code a lot clearer and shorter still.

boost::python::interpreter will allow you to easily setup the interpreter, run scripts, evaluate expressions, etc. And all the while you'll be dealing with boost::python::objects, not PyObject*s and probably not even boost::python::handle<>s. There is however a Boost.Python bug to be fixed before this can be added.

hoping-that-was-helpful-ly yours,
Dirk Gerrits


<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise