Я должен написать код, чтобы сделать некоторую обработку в режиме реального времени, которая справедливо в вычислительном отношении сложна. Я хотел бы создать некоторые классы Python, чтобы управлять всеми моими сценариями и оставить интенсивные части алгоритма кодированными в C++ так, чтобы они могли работать максимально быстро. Я хотел бы инстанцировать объектов в Python и иметь звон алгоритмов C++ назад в сценарий с обратными вызовами в Python. Что-то как:
myObject = MyObject()
myObject.setCallback(myCallback)
myObject.run()
def myCallback(val):
"""Do something with the value passed back to the python script."""
pass
Это будет возможно? Как я могу выполнить обратный вызов в Python от цикла, который работает в модуле C++? У кого-либо есть ссылка или учебное руководство, чтобы помочь мне сделать это правильно?
Я предлагаю использовать Boost.Python, как предложил ChristopheD. Проблема может возникнуть, если расширение C++ работает в собственном контексте потока (не создаваемом Python). В этом случае при вызове кода Python из C++ убедитесь, что используются функции PyGILState_Ensure()
и PyGILState_Release()
.
Из документации (http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock):
Начиная с версии 2.3, потоки теперь могут использовать преимущества функции функции PyGILState_*() для выполнения всего все вышеперечисленное автоматически. Типичная идиома для вызова в Python из потока C теперь выглядит так:
PyGILState_STATE gstate; gstate = PyGILState_Ensure(); /* Выполните здесь действия Python. */ result = CallSomeFunction(); /* Оценить результат */ /* Освободите поток. После этого момента не разрешается использовать Python API. */ PyGILState_Release(gstate)
Я рекомендую сделать обратные вызовы короткими и милыми - чтобы ограничить необходимость выполнения обработки исключений в коде C++. Если вы используете wxPython, вы можете использовать его надежную систему асинхронных событий. Или обратные вызовы могут помещать события в очередь, и у вас может быть поток, предназначенный для асинхронного выполнения кода обратных вызовов/событий.
Даже с помощью магии Boost.Python вам придется познакомиться с этой частью API Python C при работе с потоками. (Не забудьте обернуть функции C++ с помощью Py_BEGIN_ALLOW_THREADS
и Py_END_ALLOW_THREADS
, чтобы освободить GIL!)
Вот пример того, как сделать обратные вызовы на python, используя Cython. Возможно, стоит взглянуть и на Pyrex. Оба могут сделать интеграцию C/C++ с Python довольно простой.
На работе мы часто делаем то, что делаете вы. Мы любим python, но иногда он просто недостаточно быстр. Для этого хорошо подходят
Boost и Swig. Вы также должны проверить эту ссылку о Python Performance, там немного говорится о NumPy, который может вам помочь.
Взгляните на Boost.Python . Его руководство начинается здесь .