1

I have a C++ value type wrapped with Boost.Python which has a concept of a NULL value. The relevant parts of the wrapper code appear as follows:

class_<TCurrency> currency( "TCurrency" )
    .def( init<long>() )
    .def( init<const std::string&>() )
    <...>;

Currently, trying to create a NULL instance in Python by passing None to the __init__() method causes the C++ ctor accepting a const string reference to be called with an invalid reference. (&arg == NULL)

Is it possible to trap the case where None is being passed to a constructor and handle it gracefully or at least to throw a meaningful exception before my program crashes?

Using Boost 1.36 and Python 2.6.2.

1 Answer 1

2

Adding an init<void*> overload will pass NULL if None is used, but I'm not sure how this could affect other ctors in corner cases. I also don't get the same None to string const& conversion that you mention, if I leave init<void*> out. Using Boost.Python 1.37 and Python 2.6.2.

Example:

#include <iostream>
#include <string>

#include <boost/python.hpp>


struct A {
#define BODY { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    A() BODY
    A(long) BODY
    A(std::string const&) BODY
    A(void* p) BODY
#undef BODY
};

BOOST_PYTHON_MODULE(ex) {
using namespace boost::python;
class_<A>("A")
    .def(init<long>())
    .def(init<std::string const&>())
    .def(init<void*>())
;
}
>>> import ex
>>> ex.A()
A::A()
<ex.A object at 0x839bf7c>
>>> ex.A(42)
A::A(long int)
<ex.A object at 0x839bfcc>
>>> ex.A("abc")
A::A(const std::string&)
<ex.A object at 0x839bf7c>
>>> ex.A(None)
A::A(void*)
<ex.A object at 0x839bfcc>

If init<void*> is left out:

>>> ex.A(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    A.__init__(A, NoneType)
did not match C++ signature:
    __init__(_object*, std::string)
    __init__(_object*, long)
    __init__(_object*)
Sign up to request clarification or add additional context in comments.

2 Comments

It does seem like there should be an adapter or similar you should be able to apply to, for example, make A(None) use the default ctor. I'm glad you asked this question and I'll be looking forward to a more detailed answer. (From someone else.. ><)
Interesting. I don't really want to modify the original C++ class to accept a void*, but I've attempted to define an init outside the class. It doesn't actually create an object correctly (this will be the subject of another question) but at least I get a Python tb instead of a crash. Yay! =]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.