[C++-sig] Handling Python exceptions from an exposed C++ function

Francesco Biscani bluescarni at gmail.com
Sun Nov 16 19:51:14 CET 2014


Hello all,

I don't know if the subject makes any sense, but hopefully the description
of the problem will make things clearer :)

I have a template class which I am exposing to Python with different types
instantiated. For the sake of simplicity, let's say it is a Vector<T>
class. I have various versions of this class exposed, Vector<int>,
Vector<double>, etc. and everything works fine.

Recently, I thought it would be nice to have, on the Python side, a version
of my Vector class that can hold any type of Python object (a bit like the
builtin list class). Initially, I thought I could expose the C++ class
Vector<bp::object> and would hope that everything would work automagically.

Unfortunately, for my own purposes I need that the objects stored in a
Vector have C++ semantics wrt copy constructors. This means that I need to
be able to do deep copies of the stored object via their copy constructor,
for instance, and this is clearly not the case for bp::object. Moreover, I
need to be able, e.g., to negate an object with the unary "-" operator,
which is not possible for bp::object. Etc. etc.

So what I did at this point was to create a C++ class, which I called
"bp_object", that just wraps a bp::object and adds the desired features:

class bp_object
{
  // ...
  // Copy/move ctors, assignments, additional operators, etc.
  // ...
  private:
    bp::object m_object;
};

Then I added the necessary (trivial) converters to/from Python, registered
the conversion with the Boost.Python mechanism, and exposed the
Vector<bp_object> class to Python (note that the bp_object class is *not*
exposed or visible from Python).

Everything works fine until some Python exception is thrown within the
bp_object class. For instance, upon insertion into a Vector of a value, I
check from C++ that the value being inserted is not zero. I implemented the
comparison operator for bp_object as:

bool operator==(const bp_object &other) const
{
  return m_object == other.m_object;
}

This can result in an exception being thrown from Python (e.g., comparison
of a numpy array with zero). What happens in this case is that
a bp::error_already_set is thrown and not caught by anything, and the
execution terminates.

I can catch the error_already_set in the comparison operator, print
information about the Python exception that was thrown, etc. but what I
clearly need to do here is to stop the execution of the program and somehow
get back to the Python interpreter and translate the exception.

How would I do that? Does what I am trying to do make any sense or is it
unnecessarily complicated? It seems like this kind of usage is a mix
between extending and embedding, and I am not sure if this is supported at
all.

Cheers,

  Francesco.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20141116/0d0be419/attachment.html>


More information about the Cplusplus-sig mailing list