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

Paul O. Seidon p.oseidon at datec.at
Sat Oct 27 18:37:57 CEST 2012


I see, thank you Holger,

I did something similar at first, I did the registering and calling in a 
Python wrapper. But creating an EventEmitter is rather expensive compared to 
the creation of a Variable impl'ed in cpp. So I wanted to move that code to 
cpp too.

BTW, SWIG does it this way too. There you have to add code wich is called 
before/after the call into cpp.

Tanks
Paul


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




More information about the Cplusplus-sig mailing list