Pybind11: обратный вызов C++ из фонового потока в Python не выполняется в реальном времениC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Pybind11: обратный вызов C++ из фонового потока в Python не выполняется в реальном времени

Сообщение Anonymous »

Я пытаюсь предоставить Python интерфейс C++ и систему обратного вызова с помощью pybind11. В C++ все работает как положено: обратный вызов запускается в реальном времени из фонового потока. Однако в Python обратный вызов не запускается во время выполнения. Только в конце, после завершения основной программы, появляются все выходы сразу. Я пытался выяснить, как мне может понадобиться управлять получением GIL, но, насколько я понял, это должно делаться автоматически с помощью батута. Все еще безуспешно пытался получить GIL вручную.
Есть ли что-то, чего мне явно не хватает? Способен ли Python/Pybind обрабатывать такие виды асинхронных вызовов функций?
Надеюсь, следующий минимальный пример пояснит, чего я пытаюсь достичь.
Собственный код C++:
// Interface definition
class IMessageHandler {
public:
virtual ~IMessageHandler() = default;
virtual void onMessage(const std::string& msg) = 0;
};

// Class that stores an IMessageHandler and invokes it via callback
class MessageProcessor {
public:
MessageProcessor(IMessageHandler* handler)
: m_handler(handler), m_running(false) {}

// Usually this would be called from another thread
void simulateIncomingMessage(const std::string& msg) {
std::lock_guard lock(m_mutex);
m_queue.push_back(msg);
}

// Start a thread that polls for new messages and calls onMessage
void startMessenger() {
m_running = true;
m_thread = std::thread([this]() {
while (m_running) {
std::vector local_msgs;
{
std::lock_guard lock(m_mutex);
local_msgs.swap(m_queue);
}
for (const auto& msg : local_msgs) {
if (m_handler) {
m_handler->onMessage(msg);
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
}

void stopMessenger() {
m_running = false;
if (m_thread.joinable())
m_thread.join();
}

~MessageProcessor() {
stopMessenger();
}

private:
IMessageHandler* m_handler;
std::thread m_thread;
std::atomic m_running;
std::vector m_queue;
std::mutex m_mutex;
};

Pybind11:
// Pybind11 trampoline for IMessageHandler
class PyIMessageHandler : public IMessageHandler {
public:
using IMessageHandler::IMessageHandler;

void onMessage(const std::string& msg) override {
// py::gil_scoped_acquire gil; //This has no effect

PYBIND11_OVERLOAD_PURE(
void,
IMessageHandler,
onMessage,
msg
);
}
};

PYBIND11_MODULE(message_module, m) {
py::class_(m, "IMessageHandler")
.def(py::init())
.def("onMessage", &IMessageHandler::onMessage);

py::class_(m, "MessageProcessor")
.def(py::init())
.def("startMessenger", &MessageProcessor::startMessenger)
.def("stopMessenger", &MessageProcessor::stopMessenger);
}

Python:
import time
from message_module import IMessageHandler, MessageProcessor

class MyHandler(IMessageHandler):
def onMessage(self, msg):
print("Python received:", msg)

handler = MyHandler()
processor = MessageProcessor(handler)
processor.startMessenger()

time.sleep(2)

processor.stopMessenger()


Подробнее здесь: https://stackoverflow.com/questions/797 ... n-real-tim
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»