Serialize C ++ объект для отправки через сокеты в Python - лучший подход?
Мне нужно создать сетевую связь между двумя разными фреймворками, одна из которых написана наC++
а другой вPython
.
Для обмена данными я хочу создать какую-то гибкую структуру (в основном структуру) вC++
, который сериализуется, отправляется через сокеты наPython
а затем десериализовал.
Какой самый распространенный способ сделать это? Я уверен в том чтоBoost
может сделать это с любой стороны, так как естьboost python
, но я не хочу слишком сильно взрывать требования проекта. Так может ли быть небольшая библиотека или какое-нибудь другое элегантное решение, кроме указания собственного двоичного формата данных?
ОБНОВИТЬ
Так вот один пример, как использовать Googlesprotobuf
для отправки структуры данных изC++
сценарий кPython
скрипт черезUDP
. Это проверено на Mac OS X Mavericks, но должно работать и на других системах Unix.
Устанавливаем protobuf
Первым шагом, конечно, является установкаprotobuf
библиотека. Я использовал Доморощенного для основной библиотеки иpip
чтобы установитьPython
модули:
brew install protobuf
pip install protobuf
Затем я определил очень простую структуру данных, используя протосинтаксис:
Filename: foo.proto
package prototest;
message Foo {
required int32 id = 1;
required string bar = 2;
optional string baz = 3;
}
Этот прото-файл теперь может быть переведен в классы C ++ и Python с помощью:
protoc foo.proto --cpp_out=. --python_out=.
Папка должна теперь содержать заголовочные и исходные файлы C ++ и код Python:
├── foo.pb.cc
├── foo.pb.h
├── foo.proto
└── foo_pb2.py
Давайте посмотрим на самые основныеC++
код, который предназначен для отправки экземпляраfoo
по сети, используя UDP (к localhost через порт 5555):
Filename: send.cc
#include <sys/socket.h>
#include <arpa/inet.h>
// this is our proto of foo
#include "foo.pb.h"
int main(int argc, char **argv)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
inet_aton("127.0.0.1", &addr.sin_addr);
addr.sin_port = htons(5555);
// initialise a foo and set some properties
GOOGLE_PROTOBUF_VERIFY_VERSION;
prototest::Foo foo;
foo.set_id(4);
foo.set_bar("narf");
// serialise to string, this one is obvious ; )
std::string buf;
foo.SerializeToString(&buf);
int sock = socket(PF_INET, SOCK_DGRAM, 0);
sendto(sock, buf.data(), buf.size(), 0, (struct sockaddr *)&addr, sizeof(addr));
return 0;
}
Я скомпилировал это черезclang++
:
clang++ -o send send.cc foo.pb.cc -lprotobuf
И, наконец, этоPython
код, который ожидает UDP-пакеты и десериализует их вfoo
. Опять же: никаких ошибок при проверке, это только для демонстрации функциональности:
Filename: receive.py
import socket
from foo_pb2 import Foo
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("127.0.0.1", 5555))
foo = Foo()
while True:
data, addr = sock.recvfrom(1024)
foo.ParseFromString(data)
print("Got foo with id={0} and bar={1}".format(foo.id, foo.bar))
Теперь мы закончили, и это окончательная структура каталогов:
├── foo.pb.cc
├── foo.pb.h
├── foo.proto
├── foo_pb2.py
├── receive.py
├── send
└── send.cc
Чтобы проверить скрипт, просто запуститеreceive.py
для прослушивания пакетов UDP через
python receive.py
и следите за выводом при выполнении сгенерированного C ++send
скрипт:
./send