2016-07-09 12 views
0

Auf der offiziellen Website gibt es eine nice and relatively comprehensive example von, wie man CapnProto für C++ - Serialisierung verwenden könnte. Was fehlt, ist die Handhabung des zweiten Blob-Typs capnp::Data, da nur capnp::Text abgedeckt ist.So erhalten Sie byte [] in capnp :: Data

Nur der Vollständigkeit halber, hier ist das, was die Schema-Sprache sagt über die Blob-Typ:

Blobs: Text, Daten

...

  • Text immer UTF- 8 kodiert und NUL-terminiert.

  • Daten sind eine völlig willkürliche Folge von Bytes.

Also, wenn ich das folgende Schema

struct Tiding { 
    id @0 :Text; 
    payload @1 :Data; 
} 

haben kann ich meine Nachricht Gebäude wie dieses

::capnp::MallocMessageBuilder message; 
Tiding::Builder tiding = message.initRoot<Tiding>(); 

tiding.setId("1"); 

An dieser Stelle ich stecken geblieben. Ich kann das nicht tun:

typedef unsigned char byte; 

byte data[100]; 
... //populate the array 
tiding.setPayload(data) 
//error: no viable conversion from 'byte [100]' to '::capnp::Data::Reader' 

So muckte ich ein bisschen herum und sah, dass capnp :: Daten kj::ArrayPtr<const byte> wickelt, aber ich war nicht in der Lage, irgendwie einen Einfluß eines ArrayPtr zu bekommen, viel weniger es verwenden, um festgelegt das Payload-Feld für meine Nachricht.

Ich sah, dass es eine Möglichkeit gibt, den Standardwert für den Typ Data (d. H. payload @5 :Data = 0x"a1 40 33";) festzulegen, aber die Schemasprache übersetzt in diesem Fall nicht wirklich in C++, so dass auch mir nicht geholfen hat.

Ich wäre dankbar, wenn jemand darauf hinweisen könnte, was ich hier vermisse. Auch, wie würde ich das tun, wenn ich List(Data) anstelle von nur Data als Payload in meinem Schema hätte?

+0

Abgesehen: http://stackoverflow.com/questions/1725855/ uint8-t-vs-unsigned-char (Frage ist markiert C++ 11) – kfsone

+0

Ich bin bewusst 'uint8_t', aber die unsigned char typedef wird innerhalb CapnProto (KJ, tatsächlich) verwendet, also ging ich damit. – Dave

Antwort

2

Ein kj::ArrayPtr ist im Grunde ein Paar von einem Zeiger und einer Größe.

Sie können einen erstellen, indem Sie kj::arrayPtr() aufrufen, die zwei Argumente benötigt: einen Zeiger und die Array-Größe. Beispiel:

byte buffer[256]; 
kj::ArrayPtr<byte> bufferPtr = kj::arrayPtr(buffer, sizeof(buffer)); 

kj::ArrayPtr hat begin()end() und Methoden, die Zeiger und eine size() Methode zurück. So können Sie konvertieren zurück zu Zeiger/Größe wie:

byte* ptr = bufferPtr.begin(); 
size_t size = bufferPtr.size(); 

setzen sie alle zusammen, in Ihrem Beispiel, Sie wollen:

tiding.setPayload(kj::arrayPtr(data, sizeof(data))); 
+0

Eine Antwort des Autors selbst, genial!Es stellte sich heraus, dass ich das schon hatte, aber meine IDE (CLion, in diesem Fall) sagte mir immer wieder, dass es einen 'Typparameter-Mismatch gibt: Class 'kj :: ArrayPtr ' ist nicht kompatibel mit der Klasse 'capnp :: Data :: Reader "". Kompiliert und läuft gut. Ich werde nachforschen und vielleicht einen Fehler melden. – Dave

+0

Odd, da ist definitiv ein Konstruktor definiert. BTW, ich habe gerade festgestellt, dass es auch einen 'capnp :: Data :: Reader (ptr, size)' Konstruktor gibt, der CLion weniger verwirren könnte? –

+0

CLion Beklagt sich nicht über den 'capnp :: Data :: Reader (ptr, size)' -Konstruktor. Vielen Dank! – Dave