Я пытаюсь предоставить 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
Pybind11: обратный вызов C++ из фонового потока в Python не выполняется в реальном времени ⇐ C++
Программы на C++. Форум разработчиков
1761285794
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()
Подробнее здесь: [url]https://stackoverflow.com/questions/79798430/pybind11-c-callback-from-background-thread-to-python-not-executed-in-real-tim[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия