31

I want to pass callback from my python code to c++

I want my code look something like this: In C++ :

typedef void (*MyCallback_t) (CallbackInfo);

class MyClass
{...
   void setcallback(MyCallback_t cb);
 ...
}

And to use it in python :

import mylib

def myCallback(mylib_CallbackInfo):
...

t = mylib.MyClass()
t.setcallback(myCallback)

I saw some topics near my problem but couldn't solve it

For example here : Realtime processing and callbacks with Python and C++ there is advice to use boost::python and warning about GLI but no examples. And here

How to call a python function from a foreign language thread (C++) there is no full description with python code part and with "BOOST_PYTHON_MODULE" part

I also found link to use py_boost_function.hpp for example in Boost python howto but it didn't compile and actualy I couldn't understand how to use it.

Community
  • 1
  • 1
Igor Pavlov
  • 325
  • 3
  • 8

2 Answers2

22

Ok, I'm still trying to figure this out too, but here's whats working for me so far:

#this is the variable that will hold a reference to the python function
PyObject *py_callback;

#the following function will invoked from python to populate the call back reference
PyObject *set_py_callback(PyObject *callable)
{
    py_callback = callable;       /* Remember new callback */
    return Py_None;
}
...
#Initialize and acquire the global interpreter lock
PyEval_InitThreads();

#Ensure that the current thread is ready to call the Python C API 
PyGILState_STATE state = PyGILState_Ensure();

#invoke the python function
boost::python::call<void>(py_callback);

#release the global interpreter lock so other threads can resume execution
PyGILState_Release(state);

The python function is invoked from C++, and executes as expected.

nont
  • 9,322
  • 7
  • 62
  • 82
  • Yes, I did it exactly like you. But forgot to write here about it. – Igor Pavlov Sep 30 '11 at 08:41
  • Is there a lack of reference counting in this example? – Sven Dec 09 '13 at 16:37
  • 2
    How would you pass data such as a `vector` to the python callback? – Pat Mustard Jan 29 '14 at 06:47
  • I'm very interested in this question. Would you care to elaborate on this answer? Could you explain what each line of code is doing? – thomas Jul 09 '14 at 12:27
  • 1
    Sure! its been awhile since I did this, but I've annotated each line for you. googling for each function will find you more documentation. – nont Jul 09 '14 at 15:09
  • What about a single-threaded program - are those PyEval_InitThreads(), PyEval_InitThreads() and PyGILState_Release(state) really needed?; – o.z Nov 23 '14 at 10:53
  • Nobody addressed @Sven's question - is reference counting ok here (I'm thinking of functions that close over other variables, keeping them alive) – sehe Nov 15 '16 at 16:05
  • What is the python side? I cannot find the way to pass the python method as parameter. – Max Oct 10 '19 at 19:48
1

These test files from the boost::python source code repository contains great examples about how to pass callbacks from Python into C++:

duxtinto
  • 379
  • 4
  • 6
  • A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](/help/deleted-answers) – Sabito stands with Ukraine Nov 21 '20 at 04:51