Сериализиране на C++ обект за изпращане чрез сокети към Python - най-добрият подход?

Трябва да създам мрежова комуникация между две различни рамки, едната написана на C++, а другата на Python.

За обмен на данни искам да създам някакъв вид гъвкава структура (основно структура) в C++, която се сериализира, изпраща през сокети до Python и след това се десериализира.

Кой е най-често срещаният начин за това? Сигурен съм, че Boost може да го направи и от двете страни, тъй като има boost python, но не искам да взривявам толкова много изискванията на проекта. И така, има ли може би по-малка библиотека или каквото и да е друго елегантно решение, освен посочване на собствен двоичен формат на данни?

АКТУАЛИЗАЦИЯ:

Ето един пример как да използвате Googles protobuf за изпращане на структура от данни от C++ скрипт към Python скрипт чрез UDP. Това е тествано на Mac OS X Mavericks, но трябва да работи добре и на други Unix системи.

Инсталиране на protobuf

Първата стъпка, разбира се, е инсталирането на библиотеката protobuf. Използвах homebrew за основната библиотека и pip за инсталиране на Python модулите:

brew install protobuf
pip install protobuf

След това дефинирах много проста структура от данни, използвайки протосинтаксиса:

Име на файл: 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):

Име на файл: 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. Отново: никаква проверка за грешки, това е само за демонстрация на функционалността:

Име на файл: 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

person tamasgal    schedule 21.05.2014    source източник
comment
Звучи като протоколните буфери на Google може да са подходящи тук.   -  person Lukas Graf    schedule 21.05.2014
comment
Превод на обектите в XML или JSON?   -  person Some programmer dude    schedule 21.05.2014
comment
JSON е текущото ми решение, не го споменах. Благодаря също, че споменахте protobuf, все още не съм чувал за него!   -  person tamasgal    schedule 21.05.2014


Отговори (2)


Отидете за Протоколни буфери - Google Code, който има достатъчно ресурси за c++ и python. Можете да създадете съвместима структура, която да се чете и на двата езика.

Протоколните буфери са метод за сериализиране на структурирани данни. Като такива, те са полезни при разработването на програми за комуникация помежду си по кабел или за съхраняване на данни. Методът включва език за описание на интерфейса, който описва структурата на някои данни и програма, която генерира от това описание изходен код на различни езици за програмиране за генериране или анализиране на поток от байтове, който представлява структурираните данни.

person masoud    schedule 21.05.2014

Наследникът на Protocol Buffers, Cap'n Proto, също има добра поддръжка за C++ и Python. (Разкриване: Аз съм авторът на Cap'n Proto и също така бях автор на повечето от кода на Protobuf, издаден от Google.)

person Kenton Varda    schedule 22.05.2014
comment
Благодаря Кентън, ще го погледна! - person tamasgal; 22.05.2014