|
ProtocolBuffers
Objective-C Protocol Buffers for OSX and the iPhone
IntroductionProtocol Buffers are a way of encoding structured data in an efficient yet extensible format. For more information see the main page here. This project contains a port of Protocol Buffers that can be used in OSX 10.5 and later and on the iPhone OS 2.0 and later. The port includes a Protocol Buffer compiler (protoc) and a Protocol Buffer static library that you link into any project that you want protobuf support for. The protoc compiler supports almost all the features of the protobuf 2 language and when given .proto files as input will generate the specialized Objective-C classes necessary to both read and write instances of the messages contained therein. These classes, along with the supplied static library, will then allow your code to read and write protobuf instances simply and in a typesafe manner. Quick ExampleYou write a .proto file like this: message Person {
required int32 id = 1;
required string name = 2;
optional string email = 3;
}Then you compile it with protoc, the protocol buffer compiler, to produce code in Objective-C. You use that code like this to produce raw protobuf data from a message: Person* person = [[[[[Person builder] setId:123]
setName:@"Bob"]
setEmail:@"bob@example.com"] build];
NSData* data = [person data];Or like this to read a message back from raw protobuf data: NSData* raw_data = ...; Person* person = [Person parseFromData:raw_data]; Gory DetailsCreating the Protocol Buffer Compiler (protoc)In order to compiler and use protoc you must first have installed XCode and the rest of Apple's developer tools.
protoc will then be built into the <install_directory>/src directory. Compiler InvocationFor full details on the protobuf compiler, please see the official details here The protocol buffer compiler (protoc) produces Objective-C output when invoked with the --objc_out= command-line flag. The parameter to the --objc_out= option is the directory where you want the compiler to write your Objective-C output. The compiler creates a header file and an implementation file for each .proto file input. The names of the output files are computed by taking the name of the .proto file and making two changes:
protoc --proto_path=src --objc_out=build/gen src/foo.proto src/bar/baz.proto The compiler will read the files src/foo.proto and src/bar/baz.proto and produce four output files: build/gen/foo.pb.h, build/gen/foo.pb.m, build/gen/bar/baz.pb.h, build/gen/bar/baz.pb.m. The compiler will automatically create the directory build/gen/bar if necessary, but it will not create build or build/gen; they must already exist. Project IntegrationOnce you have generated the .pb.h and .pb.m files for the .proto file you care about, you can then add them to your project. However, in order to build properly several changes must be made to your project.
ExtensionsIn order to more seamlessly integrate with Objective-C code, this library also extends the standard google.protobuf.FileOptions message with the following options: // Sets the ObjectiveC package where classes generated from this .proto // will be placed. This is typically used since Objective C libraries output // all their headers into a single directory. i.e. Foundation\* // AddressBook\* UIKit\* etc. etc. optional string package = 1; // The string to be prefixed in front of all classes in order to make them // 'cocoa-y'. i.e. 'NS/AB/CF/PB' for the // NextStep/AddressBook/CoreFoundation/ProtocolBuffer libraries respectively. // This will commonly be the capitalized letters from the above defined // 'objectivec_directory' optional string class_prefix = 2; To use these extensions you will need to add the following to your proto file: import "google/protobuf/objectivec-descriptor.proto"; option (google.protobuf.objectivec_file_options).package = "<your package>" option (google.protobuf.objectivec_file_options).class_prefix = "<your class prefix>"; (note that the parent folder to 'google/protobuf/objectivec-descriptor.proto' must be in your include path when compiling your protocol buffer). By using these options, you can integrate existing protobuf definitions, while still producing Objective-C code that meets expected styling standards. For example, this library uses those options above to emit the core protobuf Descriptor types into a "ProtocolBuffers" directory with a common "PB" prefix on all classes. Thus, while you would say the following in java: import google.protobuf.Descriptor; in Objective-C you would say: import "ProtocolBuffers\PBDescriptor.h" ExampleHere's an example of how I integrate the library into my own 'Now Playing' application. Note the reference to the project, the direct dependency in the target, and the shared lib in the link section.
Help/SupportIf you need any help/support with this feel free to email me at cyrus.najmabadi@gmail.com. Cheers! |
A big big thanks to Cyrus. He's very helpful with "lost" users :)
Rename the directory of the source to something without space and special characters, like "ProtoBuff?".
Why?
Any chance to update to proto 2.3.0?
Does this port to FreeBSD?
I don't understand your question Masood.
Can you clarify on the code license of protobuf-objc?
Currently the code is covered by "GNU General Public License v2" which you have choosen for your metasyntactic project. This would prohibit using your library for commercial software. Is this intentional? Are you planning to offer a commercial license in addition?
As you can see from teh individual source files in the protobuf distro, it is apache licensed. Cheers!
I'm playing around with protcol buffers using gnustep on linux. protoc builds fine, but I'm getting import errors when I try to compile the generated files.
user@host:~/src/test$ gcc Test.pb.m -I/usr/include/GNUstep -lobjc -lgnustep-bas e -fconstant-string-class=NSConstantString -I/home/jape/ProtocolBuffers-2.2.0-S ource/objectivec/Classes In file included from /home/jape/ProtocolBuffers-2.2.0-Source/objectivec/Classes /Bootstrap.h:17, from /home/jape/ProtocolBuffers-2.2.0-Source/objectivec/Classes /ProtocolBuffers.h:15, from Test.pb.h:3, from Test.pb.m:3: /home/jape/ProtocolBuffers-2.2.0-Source/objectivec/Classes/CodedInputStream.h:27 : error: cannot find interface declaration for NSObject, superclass of PBCodedInputStreamAny ideas?
jp
Sounds like a question to ask the gnustep people about. That's not a configuration i support.
Ah. I see what's happening now. Xcode automatically includes <Framework/Framework.h> on every file for you. I was able to fix my problem by adding this to the .h files. This seemed to result in an include loop so I added
around the whole include.
It seems that this implementation only supports the serialization of data structs and doesn't support the rpc service stub generation. Is that correct?
regards
jp
Correct, only serialization of data structs.
I followed the instructions above, however, when I try to build the protocol files (.m and .h) in a test Xcode project, I get the following errors. When I look at the library(ar -t), there aren't any "PB" prefixes on any of the objects. Has anyone else had any luck with this?
errors(There are 11, I'm only attaching a couple):
"OBJC_CLASS$PBGeneratedMessage", referenced from: OBJC_CLASS$Person in Person.pb.o "OBJC_IVAR$PBGeneratedMessage.memoizedSerializedSize", referenced from: OBJC_IVAR$PBGeneratedMessage.memoizedSerializedSize$non_lazy_ptr in Person.pb.o (maybe you meant: OBJC_IVAR$PBGeneratedMessage.memoizedSerializedSize$non_lazy_ptr) "OBJC_CLASS$PBUnknownFieldSet", referenced from:
there is a bug in class codetInputStream. look at @fix tag
- (BOOL) refillBuffer:(BOOL) mustSucceed {
...
}
I'm getting a bunch of errors like the ones below when trying to compile the generated .m file.
I've copied the libProtocolBuffers.a file from ROOT/objectivec/build/Debug-iphoneos
Undefined symbols:
@ joesha...@gotspam.com
Did you resolve this? Is libProtocolBuffers.a in your linked libraries?
Are there any plans to maintain the Objective-C support of protocol buffers in the future? I just configured your solution using XCode 4 and really like it, but I'm not sure, if I can use it in an production environment, if the development has stopped.
So, any thoughts on this? ;)