How to send signal using callback called from external script?

送分小仙女□ 提交于 2019-12-07 04:15:24

We need to add some additional state to the callback, namely a reference to the instance of the class whose member function we want to invoke.

To do this, we can use a class. To make the functionality equivalent to just using a simple static callback function, let's define operator() (i.e. make it a functor), and also expose this operator to Python.

Let's suppose we have the following application class:

class app
{
public:
    explicit app(std::string name) : name_(std::move(name)) {}

    int run();

    void callback(double t_prog, double t_final);

private:
    std::string name_;
};

In run() we execute our Python script, and we want it to call the member function callback of the current instance.

Let's define the following callback handler class:

class callback_handler
{
public:
    explicit callback_handler(app& a) : app_(a) {}

    void operator()(double t_prog, double t_final)
    {
        app_.callback(t_prog, t_final);
    }

private:
    app& app_;
};

We need to expose this class to Python, but don't want to be able to create new instances from Python, nor do we really want it to be copied (although it doesn't really matter here, since our state only consists of references).

BOOST_PYTHON_MODULE(cbtest)
{
    bp::class_<callback_handler, boost::noncopyable>("callback_handler", bp::no_init)
        .def("__call__", &callback_handler::operator())
        ;
};

At the start of our application, we need to make sure to initialize our module before we use it -- call initcbtest(); right after initializing the Python interpreter.

Now we can use our callback handler in the following manner (The Python code stays the same, since the object is callable):

    callback_handler cbh(*this);
    bp::object result = MyFunc(1, 10, 2, boost::ref(cbh));
    std::cout << "result = " << bp::extract<double>(result) << "\n";

Sample Code

#include <boost/noncopyable.hpp>
#include <boost/python.hpp>

#include <iostream>
// ============================================================================
namespace bp = boost::python;
// ============================================================================
class app
{
public:
    explicit app(std::string name) : name_(std::move(name)) {}

    int run();

    void callback(double t_prog, double t_final);

private:
    std::string name_;
};
// ============================================================================
class callback_handler
{
public:
    explicit callback_handler(app& a) : app_(a) {}

    void operator()(double t_prog, double t_final)
    {
        app_.callback(t_prog, t_final);
    }

private:
    app& app_;
};
// ----------------------------------------------------------------------------
BOOST_PYTHON_MODULE(cbtest)
{
    bp::class_<callback_handler, boost::noncopyable>("callback_handler", bp::no_init)
        .def("__call__", &callback_handler::operator())
        ;
};
// ============================================================================
void app::callback(double t_prog, double t_final)
{
    std::cout << "CB(" << name_ << ") " << t_prog << " " << t_final << "\n";
}
// ----------------------------------------------------------------------------
int app::run()
{
    Py_Initialize();
    initcbtest();

    try {
        bp::object module = bp::import("__main__");
        bp::object name_space = module.attr("__dict__");
        bp::exec_file("MyModule.py", name_space, name_space);

        bp::object MyFunc = name_space["MyFunc"];

        callback_handler cbh(*this);
        bp::object result = MyFunc(1, 10, 2, boost::ref(cbh));
        std::cout << "result = " << bp::extract<double>(result) << "\n";
    } catch (bp::error_already_set&) {
        PyErr_Print();
    }

    Py_Finalize();

    return 0;
}
// ============================================================================
int main()
{
    app a("TestApp");

    return a.run();
}
// ============================================================================

Python Script

File MyModule.py:

def MyFunc(a, b, c, callback):
    result = 0
    for i in range(a, b, c):
        result += i
        callback(i, b)
    return result

Console Output

CB(TestApp) 0 10
CB(TestApp) 2 10
CB(TestApp) 4 10
CB(TestApp) 6 10
CB(TestApp) 8 10
result = 20

Maybe the problem is that you are calling emit c_n.inprogress(progr);, where the argument of the signal progr is of type double, whereas in the connect(sender, SIGNAL( inprogress(int) ), ui->progressBar, SLOT( setValue(int) ) ); the signal takes an integer as argument. In older Qt versions(older than Qt5), signals and slots must use exactly the same types, meaning that the implicit conversion may not occur.

https://forum.qt.io/topic/23302/connect-diferent-signals-and-slost-each-other/4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!