Hello, We are using Boost.Python to embed a Python interpreter. We have some existing classes whose ownership semantics don't play very nicely with being instantiated from Python, which we really want to do. It's unfortunately not possible for us to improve this, due to a large existing codebase; we don't want to harm our existing projects in the process of adding Python support.
However, what we can do, is tell these instances when they have been instantiated from within Python, and then everything will work great. We were able to use no_init and make_constructor to use a custom constructor that would construct the object, and then call an extra function. However, we wanted to make this happen globally for all classes that inherit from a base class that we have, since requiring people to remember to do this every time a new class is exposed is likely to lead to bugs. I was able to accomplish this by having value_holder call a function after constructing its held object. The function, boost_python_value_holder_post_init(), is called with a pointer to the newly constructed object, without namespace qualification (to enable ADL), and the default implementation takes a bool as its parameter, in order to be the worst possible candidate in overload resolution. This allows us to implement void boost_python_value_holder_post_init(BaseClass*) within the same namespace that BaseClass is defined in, and then our version of the function will get called any time that a subclass of BaseClass is constructed from within Boost.Python. I'm attaching my patch below. I would really appreciate any feedback as to whether this general concept is something Boost.Python would consider merging in, and if so, if there's anything I can do in terms of how my patch is implemented in order to make it more suitable. I'd also be happy (and interested!) to discuss any alternate ways to accomplish what I want. To reiterate, it's really important to us that we be able to do this for all subclasses of a certain class, automatically, and this was the only apparent mechanism to me. The patch follows below. Thanks for your time! Best regards, Aaron Wishnick --- a/boost/python/object/value_holder.hpp +++ b/boost/python/object/value_holder.hpp @@ -33,6 +33,17 @@ namespace boost { namespace python { namespace objects { +// After a value_holder initializes its held object, this +// function will be called with a pointer to the held object. +// Note that it will be called with ADL, so you should define +// it in the same namespace as that of the object you want to +// have this called on. This function takes a bool as a catchall +// because pointer to bool conversion is the "worst" standard +// conversion, and any other custom overload written by a client +// should be called instead. +inline void boost_python_value_holder_post_init(bool) { +} + # if BOOST_WORKAROUND(__GNUC__, == 2) # define BOOST_PYTHON_UNFORWARD_LOCAL(z, n, _) BOOST_PP_COMMA_IF(n) (typename unforward<A##n>::type)objects::do_unforward(a##n,0) # else @@ -137,6 +148,7 @@ void* value_holder_back_reference<Value,Held>::holds( BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil) ) { + boost_python_value_holder_post_init(&m_held); python::detail::initialize_wrapper(self, boost::addressof(this->m_held)); }
_______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig