Call Python Function that Accepts Callback From C++

Call Python Function that Accepts Callback From C++

Integrating C++ with Python can unlock powerful capabilities, but bridging the two languages comes with its challenges. One common hurdle is calling Python functions that accepts callback. This scenario arises when you need to trigger Python functions asynchronously or in response to certain events. This tutorial shows how to call a Python function that accepts callback from C++.

Imagine we've got a Python script named test.py, where we define a function that takes a callback as an argument:

test.py

def call(callback):
    callback(2.0, 5.0)

We created the C++ program that calls the call function. The code retrieves the current script's path and adds it to Python's sys.path, allowing the importation of the module. It imports a Python module named test and retrieves a function named call from it. Next, it defines a callback function and creates a Python object representing it. Finally, it calls the call, passing the callback object as an argument. The C++ function is invoked as a callback from Python, receiving two arguments, which printed to the console.

main.cpp

#include <Python.h>
#include <filesystem>
#include <iostream>

static PyObject *callback(PyObject *self, PyObject *args) {
    double first = PyFloat_AsDouble(PyTuple_GetItem(args, 0));
    double second = PyFloat_AsDouble(PyTuple_GetItem(args, 1));
    std::cout << first << ' ' << second << std::endl;

    return Py_None;
}

int main(int argc, char *argv[])
{
    std::filesystem::path script(argv[0]);

    Py_Initialize();
    PyObject *sysPath = PySys_GetObject("path");
    PyList_Insert(sysPath, 0, PyUnicode_FromString(script.parent_path().c_str()));

    PyObject *pModule = PyImport_ImportModule("test");
    PyObject *pFunc = PyObject_GetAttrString(pModule, "call");

    static PyMethodDef callbackDef = {"my_callback", &callback, METH_VARARGS};

    PyObject *callbackObj = PyCFunction_New(&callbackDef, nullptr);
    PyObject_CallFunctionObjArgs(pFunc, callbackObj, nullptr);

    Py_Finalize();

    return 0;
}

Leave a Comment

Cancel reply

Your email address will not be published.