📜 ⬆️ ⬇️

Python and C ++ integration

Good day to all!

Recently, when prototyping one of the parts of the product we are developing, one interesting problem arose: it was necessary to check the gluing of Python and C ++. This was due to the fact that the main code was written on the pluses, and it was necessary to connect the external library Websockets, written in Python (at that time there was no corresponding C ++ library). The interaction scheme for such a task is quite simple. The function of connecting to the server (in python) is called from C ++, its address is passed as a parameter. Accordingly, when a message is received, Python passes it back to the C ++ method.

When writing the code, the Websocket Python library from Autobahn ( http://www.tavendo.de/autobahn/clientlibraries.html ) was used, which needed to be called from C ++. For these purposes, Python provides the Python C-API ( http://docs.python.org/extending/index.html ), but many simple actions, such as calling functions, are done by several actions. After a little googling, a number of libraries were found to simplify such actions: Boost.Python ( http://www.boost.org/doc/libs/1_39_0/libs/python/doc/index.html ), SWIG ( http: // www.swig.org/ ), Py ++, Pybindgen, Pyrex ... As a result, Boost.Python was chosen as the most popular solution.

First, let's write a simple Python echo client, which will send itself the message “Hello world” once a second, receive it and give it to C ++. cppMethods will be declared in C ++ code, cppMethods.printMessage (msg) is just the place for splicing from the Python side, directly calling the C ++ function that will print the received message.
')
Here is the Python code - 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() 


Now we will write in C ++ code in which we will describe our function, called from python. To use the Python C-API, Python.h needs to be inserted. Please note that at this stage we are not yet using Boost.Python , only the native Python C-API itself .

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} }; 


In the last declaration, we described that when the Python printMessage function was called, the C ++ printString method would be called.

Well, finally, let's tie it all together. In addition to the echo client, a link to html5labs was used to test websockets.

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(); } 

In this place, we still took advantage of the capabilities of Boost, namely the call_method function, otherwise we would have to write substantially more code.

Somehow like this. Here we initialized EmbMethods for python, calling them cppMethods , then calling the Connect method from Python and passing the string “address” to it. As a result, our application prints the string “Hello World” once a second (which the python sends to itself), as well as any message coming from the web socket server.

This is the way to link Python and C ++. I would be grateful for comments on the topic.

Upd. Corrected the code in accordance with the comments from the comments.

Source: https://habr.com/ru/post/139655/


All Articles