Интеграция Python И C++

Добрый день всем! Недавно при прототипировании одной из частей разрабатываемого нами продукта возникла интересная задача: нам нужно было проверить склейку Python и C++.

Это было связано с тем, что основной код был написан в плюсах, и нужно было подключать внешнюю библиотеку Websockets, написанную на Python (соответствующей библиотеки на C++ на тот момент не было).

Схема взаимодействия для такой задачи достаточно проста.

Из C++ вызывается функция подключения к серверу (в python), ее адрес передается как параметр.

Соответственно, когда Python получает сообщение, он передает его обратно методу C++.

При написании кода мы использовали библиотеку Python Websocket от Autobahn ( http://www.tavendo.de/autobahn/clientlibraries.html ), который нужно было вызвать из C++.

Для этих целей Python предоставляет Python C-API ( http://docs.python.org/extending/index.html ), однако многие простые действия, например вызов функций, выполняются за несколько действий.

Немного погуглив, я нашел ряд библиотек, упрощающих подобные действия: Boost.Python( http://www.boost.org/doc/libs/1_39_0/libs/python/doc/index.html ), СВИГ( http://www.swig.org/ ), Py++, Pybindgen, Pyrex. В результате самым популярным решением был выбран Boost.Python. Во-первых, давайте напишем простой эхо-клиент на Python, который будет отправлять себе сообщение «Hello world» раз в секунду, получать его и отправлять на C++.

cppMethods будет объявлен в коде C++, cppMethods.printMessage(msg) — это как раз то место, где присоединяется Python, напрямую вызывая функцию C++, которая будет печатать полученное сообщение.

Вот код Python — echo-client.py :

  
  
   

from twisted.internet import reactor from autobahn.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS import cppMethods class EchoClientProtocol(WebSocketClientProtocol): def sendHello(self): self.sendMessage("Hello, world!") def onOpen(self): self.sendHello() def onMessage(self, msg, binary): cppMethods.printMessage(msg) reactor.callLater(1, self.sendHello) def Connect(addressStr): factory = WebSocketClientFactory(addressStr) factory.protocol = EchoClientProtocol connectWS(factory) reactor.run()

Теперь давайте напишем код на C++, в котором опишем нашу функцию, вызываемую из Python. Чтобы использовать Python C-API, вам необходимо включить Python.h. Обратите внимание, что на данном этапе мы еще не используем Boost.Python , только на самом деле родной Python C-API .

PrintEmb.cpp :

#include <Python.h> #include <iostream> #include <string> static PyObject * printString(PyObject * self, PyObject* args) { const char * toPrint; if(!PyArg_ParseTuple(args, "s", &toPrint)) { return NULL; } std::cout << toPrint << std::endl; Py_RETURN_NONE; } static PyMethodDef EmbMethods[] = { {"printMessage", printString, METH_VARARGS, "Return the string recieved from websocket server"}, {NULL, NULL, 0, NULL} };

В последнем объявлении мы описали, что при вызове функции printMessage метод C++ будет вызываться из Python печатьстрока .

Что ж, давайте, наконец, свяжем все это воедино.

Для проверки работы вебсокетов помимо эхо-клиента использовалась ссылка на html5labs. WebSocketConnect.cpp :

#include <Python.h> #include <boost/python.hpp> #include <iostream> #include <string> #include "PrintEmb.cpp" void WebSocketConnect() { using namespace boost::python; Py_Initialize(); Py_InitModule("cppMethods", EmbMethods); PyObject * ws = PyImport_ImportModule("echo_client"); std::string address = " ws://html5labs-interop.cloudapp.net:4502/chat "; call_method<void>(ws, "Connect", address); Py_Finalize(); }

На этом этапе мы еще воспользовались возможностями Boost, а именно функцией вызов_метода , иначе нам пришлось бы писать значительно больше кода.

Ну вот как то так.

Здесь мы инициализировали Методы вставки для Python, вызывая их cppMethods а затем вызвал метод из Python Соединять и передал ему строку «адрес».

В результате наше приложение печатает строку «Hello World» (которую Python отправляет самому себе) раз в секунду, а также любое сообщение, поступающее от сервера веб-сокетов.

Вот как вы можете связать Python и C++.

Буду благодарен за комментарии по теме.

Обновление.

Исправил код в соответствии с замечаниями из комментариев.

Теги: #python #c plus plus #websockets #boost #python #C++

Вместе с данным постом часто просматривают: