[C++-sig] [boost.python] Register a Python-callable with C++ code and call it from C++ code?

Niall Douglas s_sourceforge at nedprod.com
Sun Oct 28 02:16:56 CEST 2012


There should be no reason you can't wrap bound Boost/C++11 Functor 
instances and pass them in as callables to Python. You might need a 
little machinery to let BPL know what the function prototype is 
(assuming BPL doesn't already understand 
boost::function/std::function), but it ought to be straightforward. 
Try 
http://wiki.python.org/moin/boost.python/HowTo#boost.function_objects 
if it's still current. Also see 
http://stackoverflow.com/questions/3687279/registering-python-callable
s-in-c-classes.

To complete the circle, calling some python callable from C++, 
boost::python::call<>() is your friend. You just need to make your 
C++ callable by python (e.g. using the above), then call it as if it 
were any other kind of python callable.

HTH,
Niall


On 27 Oct 2012 at 17:36, Holger Brandsmeier wrote:

> Paul,
> 
> if I see this correctly, then you are trying to register a function to
> python in
>       .def( "register_tau4ehS", register_tau4ehS)
> which is expecting a pointer to a function to python. You can not do
> that. Python can not pass function pointers as arguments, and so can't
> boost::python.
> 
> When I want to use the callback design pattern with python, I do the
> following. A callback is for me an _object_ with has a certain member
> function, say `call`, and that expects arguments as you want them, in
> your case EventEmitterSync3<TYPE>&. When I register the class I pass a
> shared_ptr to that object. Later I can call that object.
> 
> In python I make a wrapper for that class, and in python I derive from
> that class. Then in python I instantiate those derived classes and can
> pass them to the register method. (Usually I like to create a class in
> python that in the constructor takes a lambda function.)
> 
> -Holger
> 
> On Sat, Oct 27, 2012 at 4:12 PM, Paul O.  Seidon <p.oseidon at datec.at> wrote:
> > I want to register Python-callables with my VariableFloat-class (which is a
> > subclass of a template-class Variable<double>) and call them if the
> > variable's value changes.
> >
> > For this I added an instance of class EventEmitter, which should hold
> > references to those callbacks. So, VariableFloat delegates to EventEmitter,
> > when it comes to deal with callbacks (reg'ing and calling).
> >
> > template <class TYPE>
> > class EventEmitterSync3
> > {
> > public:
> >
> > <snip/>
> >
> >     void                        operator()() // Call the handler
> >                                 {
> >                                     if (_p_tau4eh)
> >                                         (*_p_tau4eh)( *this);
> >                                 };
> >
> >     void                        register_tau4ehS( void (*callable)(
> > EventEmitterSync3<TYPE>& )) // Register the handler
> >                                 {   _p_tau4eh = callable;
> >                                 };
> > <snip/>
> >
> > private:
> >     void                        (*_p_tau4eh)( EventEmitterSync3<TYPE>& ) =
> > NULL; // The handler
> > };
> >
> >
> > The class VariableFloat (actually its base class _Variable<TYPE>) holds a
> > member of type EventEmitterSync<TYPE> like so:
> >
> > private:
> >     EventEmitterSync3<TYPE>     _tau4ee_on_change;
> >
> > and the wrapper definitions are
> >
> > void    (VariableFloat::*register_tau4ehS)( void (*)(
> > EventEmitterSync3<double>& )) = &VariableFloat::register_tau4ehS;
> >
> > and
> >
> >         .def( "register_tau4ehS", register_tau4ehS)
> >
> >
> > Compiling yields errors coming from boost being rather cryptic to me. But
> > the last few lines say:
> >
> > /media/truecrypt13/D.X/Projects/DDG/tau4/src/cpp/src/tau4misc/main.cpp:43:1:
> > required from here
> > /usr/include/boost/python/converter/registered.hpp:86:7: error: no matching
> > function for call to ?register_shared_ptr1(void (*)
> > (EventEmitterSync3<double>&))?
> > /usr/include/boost/python/converter/registered.hpp:86:7: note: candidate is:
> > /usr/include/boost/python/converter/registered.hpp:77:3: note:
> > template<class T> void
> > boost::python::converter::detail::register_shared_ptr1(const volatile T*)
> > /usr/include/boost/python/converter/registered.hpp:77:3: note:   template
> > argument deduction/substitution failed:
> > /usr/include/boost/python/converter/registered.hpp:86:7: note:   types
> > ?const volatile T? and ?void(EventEmitterSync3<double>&)? have incompatible
> > cv-qualifiers
> >
> > Seems I have to put "const volatile" somewhere?
> >
> > I found some dox, which could be relevant, here:
> > http://www.boost.org/doc/libs/1_51_0/libs/python/doc/v2/callbacks.html
> >
> > But I am not sure how to apply that info to my problem. I tried to change
> > all function pointers into objects, but that didn't work.
> >
> > Has anyone some sample code on storing pointers to Python functions and then
> > calling them and is willing to share it?
> >
> > Paul
> >
> >
> >
> >
> >
> >
> > _______________________________________________
> > Cplusplus-sig mailing list
> > Cplusplus-sig at python.org
> > http://mail.python.org/mailman/listinfo/cplusplus-sig
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig


-- 
Any opinions or advice expressed here do NOT reflect those
of my employer Research In Motion Inc.
Work Portfolio: http://careers.stackoverflow.com/nialldouglas/



-------------- next part --------------
A non-text attachment was scrubbed...
Name: SMime.p7s
Type: application/x-pkcs7-signature
Size: 6061 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20121027/19acce4f/attachment-0001.bin>


More information about the Cplusplus-sig mailing list