0

I am currently using google's protocol buffers. It works painlessly between Java and C#, however I am running into problems trying to achieve the same use with Obj-c.

The Java WS returns a byte[]. The code that uses the protocol buffer API is simple enough:

productGroup.toByteArray();

I am able to recreate the object with Skeet's C# port, using:

byte[] result = searchWebService.SearchProductsProtocolBuffer(search);
ProductProtoGroup products = ProductProtoGroup.ParseFrom(result);

However, on the obj-c side, I am struggling to work with the return value.

The NSString I receive from the same web service RPC is this:

CmYKEzgwMDAwMUFELTEzMjUyNzk5MTQySUZPT0QgJiBCRV...

I'm not quite sure what to do with this, because I don't know what it is, save it was generated from an array of bytes. I tried parsing it directly to NSData using

NSData* data = [returnValue dataUsingEncoding:NSUTF8StringEncoding];

but on [ProductProtoGroup parseFromData:data];, I get an InvalidProtocolBuffer

I've checked on the Java side what byte string/hexadecimal representations of the original byte[], and it doesn't match the string I receive from the ws.

Hexadecimal is 0-F. Perhaps each byte was converted to a char? No, that doesn't match.

Any help would be appreciated.

Dane

Danedo
  • 2,193
  • 5
  • 29
  • 37

2 Answers2

1

With a fresher mind and some helpful comments, I finally got it.

I was wondering how the web service automagically sent a byte[] in Java, then reconstructed it in C# later, and also how to store this message later.

Turns out the string,

CmYKEzgwMDAwMUFELTEzMjUyNzk5MTQySUZPT0QgJiBCRV...

was indeed what was being sent in the soap envelopes. So inbetween creation of a byte[] in Java and transmission, something was happening. Looking at the message handler in C#,

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", 
    RequestNamespace="x", ResponseNamespace="x", 
    Use=System.Web.Services.Description.SoapBindingUse.Literal, 
   ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("return",
   Form=System.Xml.Schema.XmlSchemaForm.Unqualified, 
   DataType="base64Binary", IsNullable=true)]
public byte[] searchProductProtocolBuffer([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] string arg0)
{
   object[] results = this.Invoke("searchProductProtocolBuffer", new object[] {
                    arg0});
   return ((byte[])(results[0]));
}

So base64Binary!, which I admittedly am meeting for the first time. Poking around, Skeet says it is the safest way:

How can I safely convert a byte array into a string and back?

So, knowing the encoding, the solution becomes straight forward. Using the algorithm presented in an answer to this question: How do I do base64 encoding on iphone-sdk?, my final code becomes:

NSString* returnValue = [WebServiceUtil processStringReturnValue:value];
NSData* data = [Encoding base64DataFromString:returnValue];
ProductProtoGroup* products = [ProductProtoGroup parseFromData:data];
Community
  • 1
  • 1
Danedo
  • 2,193
  • 5
  • 29
  • 37
0

I know very little about Objective C, but an NSString is no byte array. Have you tried converting the NSString to char* using -[NSString UTF8String]?

djf
  • 6,592
  • 6
  • 44
  • 62