Re: [protobuf] c++ to java issue (zero tag)

499 views
Skip to first unread message

Ilia Mirkin

unread,
Dec 5, 2012, 2:16:05 PM12/5/12
to valadas, prot...@googlegroups.com
You're giving Java a 4096-byte buffer, even though there are only 33
bytes. The parser gets confused by the trailing 0's. A protocol
message does not encode, itself, how long it is. If you know that it
doesn't fill the whole byte array, you should use
bla.newBuilder().mergeFrom(byte[], off, len) or truncate the byte
buffer yourself.

On Wed, Dec 5, 2012 at 10:37 AM, valadas <valadas...@gmail.com> wrote:
> Hello I'm trying to use protobuf 2.4.1 to exchange messages between c++ and
> java.
>
> I have defined a .proto file (attached) with two union messages ,one to be
> sent from java to c++ and other the other way around.
>
> I started testing the c++ but I'm not able to receive the message in the
> java side (I got an exception about a zero tag)
>
> The C++\QT code is as follows:
>
>
> char buf[4096];
>
> operational_gui::OperationalMessage message;
> message.set_type(operational_gui::OperationalMessage::OWNPOSITIONREPORT);
> message.mutable_oprep()->set_latitude(38.5);
> message.mutable_oprep()->set_longitude(-9.8);
> message.mutable_oprep()->set_heading(25);
> message.mutable_oprep()->set_validity(0);
>
>
> message.SerializeToArray(buf, message.ByteSize());
> m_pSocket->write(buf, message.ByteSize());
> m_pSocket->flush();
>
> the m_pSocket is a QLocalSocket
>
> on the java I have the following code:
>
> FileinputStream pipe = new FileinputStream(pipeName);
> char buffer = new char[4096];
>
> pipe.read(buffer);
>
> MessagesProtos.OperationalMessage message =
> MessagesProtos.OperationalMessage.parseFrom(buffer);
>
> switch(message.getType()){
> case OWNPOSITIONREPORT:
> System.out.println("Response is OwnPositionReport");
> break;
> case FRIENDPOSITIONREPORT:
> System.out.println("Response is FriendPositionReport");
> break;
> case COMMSTATUSREPORT:
> System.out.println("Response is CommStatusReport");
> break;
> }
>
>
> But parseFrom always give an exception stating "Protocol message contained
> an invalid tag (zero)"
>
> The buffer sent is the same that is received on java (33 bytes, see
> attachment)
>
> Any hints ?
>
> Thanks in advance
>
> --
> You received this message because you are subscribed to the Google Groups
> "Protocol Buffers" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/protobuf/-/dvVqzdUPecgJ.
> To post to this group, send email to prot...@googlegroups.com.
> To unsubscribe from this group, send email to
> protobuf+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/protobuf?hl=en.

Christopher Head

unread,
Dec 5, 2012, 7:09:50 PM12/5/12
to valadas, prot...@googlegroups.com
On Wed, 5 Dec 2012 07:37:40 -0800 (PST)
valadas <valadas...@gmail.com> wrote:

> *FileinputStream pipe = new FileinputStream(pipeName);*
> *char buffer = new char[4096];*
> **
> *pipe.read(buffer);*
> *
> MessagesProtos.OperationalMessage message =
> MessagesProtos.OperationalMessage.parseFrom(buffer);
>

Protobuf messages are binary. Use bytes here, not chars. In fact this
code shouldn’t even compile; java.io.FileInputStream doesn’t *have* a
read() method that takes a char array!

Chris

valadas

unread,
Dec 6, 2012, 6:48:53 AM12/6/12
to prot...@googlegroups.com

Quarta-feira, 5 de Dezembro de 2012 15:37:40 UTC, valadas escreveu:
Hello I'm trying to use protobuf 2.4.1 to exchange messages between c++ and java.
 
I have defined a .proto file (attached) with two union messages ,one to be sent from java to c++ and other the other way around.
 
I started testing the c++ but I'm not able to receive the message in the java side (I got an exception about a zero tag)
 
The C++\QT code is as follows:
 

char buf[4096];

operational_gui::OperationalMessage message;
message.set_type(operational_gui::OperationalMessage::OWNPOSITIONREPORT); 
message.mutable_oprep()->set_latitude(38.5); 
message.mutable_oprep()->set_longitude(-9.8); 
message.mutable_oprep()->set_heading(25); 
message.mutable_oprep()->set_validity(0);
 

message.SerializeToArray(buf, message.ByteSize());
m_pSocket->write(buf, message.ByteSize());
m_pSocket->flush();
 
the m_pSocket is a QLocalSocket
 
on the java I have the following code:
 
FileinputStream pipe = new FileinputStream(pipeName);
char buffer = new char[4096];
 

valadas

unread,
Dec 6, 2012, 6:58:32 AM12/6/12
to prot...@googlegroups.com
You are right!
Trying to simplify the problem I made some mistakes while writing the message.
 
Meanwhile I changed the c++ code to serialize to a coded stream and it worked.
Here the latest version of the code for reference for other beginners:
 
unsigned char * buffer = new unsigned char[message.ByteSize()+1];   // size + varint byte
ZeroCopyOutputStream * os = new ArrayOutputStream(buffer,message.ByteSize()+1);  // size + varint byte
CodedOutputStream * cos = new CodedOutputStream(os); 
cos->WriteVarint32(message.ByteSize()); // shouldn't be 4 bytes ?
message.SerializeToCodedStream(cos); 
delete cos;
delete os;
m_pSocket->write((char*)buffer, message.ByteSize()+1); 
m_pSocket->flush(); 
delete buffer;
 
And on java both solutions work now:
 
FileInputStream = new FileInputStream();
 
1)
int size = pipe.read();
byte[] tmp = new byte[size];
pipe.read(tmp);
MessagesProtos.OperationalMessage.Builder builder = OperationalMessage.newBuilder();
builder.mergeFrom(tmp);
OperationalMessage message = builder.build();
 
2)
MessagesProtos.OperationalMessage message = MessagesProtos.OperationalMessage.parseDelimitedFrom(pipe);
 
Thank you all!
GV 

crotty.ch...@gmail.com

unread,
Jan 10, 2013, 10:13:13 AM1/10/13
to prot...@googlegroups.com
I have a question about this and multiple messages.

Do you create a new output stream for every message?
I was looking to reuse the output streams but don't see a way to 'clear' the underlying buffer (or reset the streams current position).

Thanks,
Chris


On Thursday, December 6, 2012 6:58:32 AM UTC-5, valadas wrote:
You are right!
Trying to simplify the problem I made some mistakes while writing the message.
 
Meanwhile I changed the c++ code to serialize to a coded stream and it workedQ.
Reply all
Reply to author
Forward
0 new messages