Sérialiser un object C ++ à envoyer via des sockets à Python – meilleure approche?

J’ai besoin de créer une communication réseau entre deux frameworks différents, l’un écrit en C++ et l’autre en Python .

Pour échanger des données, je souhaite créer une sorte de structure flexible (essentiellement une structure) en C++ , qui est sérialisée, envoyée via des sockets à Python , puis désérialisée.

Quel est le moyen le plus courant de faire cela? Je suis sûr que Boost pourrait le faire de part et d’autre, car il existe du boost python , mais je ne veux pas trop faire exploser les exigences du projet. Alors, y a-t-il une bibliothèque plus petite ou une solution élégante autre que la spécification d’un format de données binary propre?

METTRE À JOUR:

Voici donc un exemple d’utilisation de Googles protobuf pour envoyer une structure de données d’un script C++ à un script Python via UDP . Ceci est testé sur Mac OS X Mavericks mais devrait également fonctionner correctement sur les autres systèmes Unix.

Installation de protobuf

La première étape consiste bien entendu à installer la bibliothèque protobuf . J’ai utilisé homebrew pour la bibliothèque principale et pip pour installer les modules Python :

 brew install protobuf pip install protobuf 

Ensuite, j’ai défini une structure de données très simple en utilisant la proto-syntaxe:

Nom de fichier: foo.proto

 package prototest; message Foo { required int32 id = 1; required ssortingng bar = 2; optional ssortingng baz = 3; } 

Ce fichier proto peut maintenant être traduit en classes C ++ et Python via:

 protoc foo.proto --cpp_out=. --python_out=. 

Le dossier doit maintenant contenir l’en-tête C ++, les fichiers source et le code Python:

 ├── foo.pb.cc ├── foo.pb.h ├── foo.proto └── foo_pb2.py 

Jetons un coup d’œil au code C++ très basique, destiné à envoyer une instance de foo sur le réseau, en utilisant UDP (to localhost sur le port 5555):

Nom de fichier: send.cc

 #include  #include  // 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 ssortingng, this one is obvious ; ) std::ssortingng buf; foo.SerializeToSsortingng(&buf); int sock = socket(PF_INET, SOCK_DGRAM, 0); sendto(sock, buf.data(), buf.size(), 0, (struct sockaddr *)&addr, sizeof(addr)); return 0; } 

Je l’ai compilé via clang++ :

 clang++ -o send send.cc foo.pb.cc -lprotobuf 

Et enfin, il s’agit du code Python , qui attend les paquets UDP et les désérialise en foo . Encore une fois: aucune erreur de vérification, ce n’est que pour démontrer la fonctionnalité:

Nom de fichier: 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.ParseFromSsortingng(data) print("Got foo with id={0} and bar={1}".format(foo.id, foo.bar)) 

Maintenant, nous avons terminé et voici la structure de répertoires finale:

 ├── foo.pb.cc ├── foo.pb.h ├── foo.proto ├── foo_pb2.py ├── receive.py ├── send └── send.cc 

Pour tester le script, exécutez simplement receive.py pour écouter les paquets UDP via

 python receive.py 

et gardez vos yeux sur la sortie lorsque vous exécutez le script d’ send généré par C ++:

 ./send 

Optez pour les tampons de protocole – Code Google qui dispose de suffisamment de ressources pour c ++ et python . Vous pouvez créer une structure compatible lisible dans les deux langues.

Les tampons de protocole sont une méthode de sérialisation des données structurées. En tant que tels, ils sont utiles pour développer des programmes permettant de communiquer entre eux via un fil ou pour stocker des données. Le procédé implique un langage de description d’interface décrivant la structure de certaines données et un programme générant à partir de cette description le code source dans divers langages de programmation pour générer ou parsingr un stream d’octets représentant les données structurées. †

Cap’n Proto , le successeur de Protocol Buffers, prend également en charge C ++ et Python. (Divulgation: je suis l’auteur de Cap’n Proto et l’auteur de la plupart du code Protobuf publié par Google.)