By learnvst

2012-04-23 09:01:59 8 Comments

Is the metasyntactic static library for iOS . . .

. . . compatible with regular old C++ compiled protofiles? I do not want to use the bundled compiler that generates Obj-C.

Is there any way to compile the library supplied by Google for iOS?


@learnvst 2012-04-23 11:29:15

Ok. It appears that the metasyntactic library (or any other 3rd party library) is unnecessary in this case. You can just add the Google source directly to your project. I found the following answer from Nicola Ferruzzi in a google discussion group . . .

The original answer is here . . .

The content of this answer is included below with images to make a permanent record ...


Since trying this again tonight for the first time in a while, I needed a couple more steps in addition to those outlined below (this works with protobuf 2.5.0).

  • You'll need to link against libz.dylib. You set this in Build Phases > Link Binary With Libraries.
  • To easily remove all of the unit test related stuff, use the following command from the shell in the google directory find . -name "*unittest*" -exec rm -rf {} \;
  • Also delete the folder called testing
  • comment out #include <google/protobuf/testing/googletest.h> in
  • Now carefully follow the instructions below and all should work fine.

I use latest version in my app .. you don't really need objc direct support if you are familiar with C++, there is only one point where you have to pass from std::string to NSData and viceversa. And its pretty simple.

To compile and test the easiest way Ive found is to just import the whole google directory in my own project :) (the second time you can make your own framework but for testing this procedure just works)

  • download latest version
  • autogen configure and make like you were just building for macosx (you need command line tools) . This way you end up with protoc
    binary and the library for macosx (which you don't need)
  • open your Xcode iOS project
  • add "new file" to your project and select google directory
  • add the directory of google headers to your additional include directories
  • add config.h from the protobuffer src directory to your app
  • from the google group remove everything that contains unitest :)
  • from the google group remove compiler and java stuff;

You should be able to compile without any linking error. To give you an idea this is what I directly compile

enter image description here

Then you can use protoc to generate c++ source files for your protocol. To use them with objc you have to rename your source to file "mm" then you can do something like


let's say your message is called Packet

- (NSData *)getDataForPacket:(Packet *)packet { 
    std::string ps = packet->SerializeAsString(); 
    return [NSData dataWithBytes:ps.c_str() length:ps.size()]; 


- (Packet *)getPacketFromNSData:(NSData *)data { 
  char raw[[data length]]; 
  Packet *p = new Packet; 
  [data getBytes:raw length:[data length]]; 
  p->ParseFromArray(raw, [data length]); 
  return p; 


@Tavis Bones 2012-07-23 20:39:43

When you say "add the directory of google headers to your additional include directories" what does that mean? Add it to the Header Search Paths?

@learnvst 2012-07-25 11:42:07

In XCode, it means add it to the header search paths, yes. Different compiler IDEs will have different labels. All the best.

@Tony 2012-10-11 13:19:05

If someone follow this and get issue that <tr1/unordered_map> cannot be found, remove 'tr1' in config.h. And also, if you failed to compile, add include <iostream> in file.

@Bennett Smith 2013-10-19 19:11:03

Following the general instructions provided here I have build a Cocoapod that does an install of Google Protobuf v2.5.0 directly from the Google tar.gz file. It works for Xcode 5 and targets iOS 7. It also includes a build of the protoc compiler for Mac OS so it becomes possible to add Protobuf support to a project with no additional messing about. The podspec is in the main Cocoapods Specs repo. Just "pod search protobuf" to find it.

@Teddy 2014-08-25 21:01:37

After following your description and using Xcode 6 beta6 I receive the following error: 'unordered_map' file not found. What do I miss here?

@Teddy 2014-08-25 21:11:53

OK I found it. C++ language dialect must be set to C++11 and standard library to libc++.

@Oscar 2019-04-22 06:32:51

This procedure suffers from quite a few problems, at least with protobuf 3.7.1. Several (non-test-related) required header files wind up being deleted.

@Bennett Smith 2013-10-19 19:19:18

You can add support for Google Protocol Buffers to an Xcode 5 project using Cocoapods by adding the following line to your Podfile.

pod 'GoogleProtobuf', '~> 2.5.0'

This will place the C++ version of the protobuf code into a Pod for your project. It will also add the protoc compiler in the folder Pods/GoogleProtobuf/bin/protoc within your project.

You can create a custom build rule in your project that automatically converts the .proto files into .ph.{h,cc} files. Here is how I did that:

Setup a build rule to "Process Source files with names matching: *.proto Using Custom Script". The script should include the following:

${SRCROOT}/Pods/GoogleProtobuf/bin/protoc --proto_path=${INPUT_FILE_DIR} ${INPUT_FILE_PATH} --cpp_out=${INPUT_FILE_DIR}/cpp

Set the output files to include the following:


Any .proto files you include in your project will now automatically be converted to C++ and then compiled as part of your build.

@Bennett Smith 2013-10-25 06:35:08

Refer to… for another possible solution that performs a local build.

@Ted Tomlinson 2013-08-07 18:45:45

I guess based on the actual question my comment is worth posting as an answer:

I'm using a slightly modified version of the native Obj code generation provided by Booyah

It supports repeated fields out of the box but in order to use ObjC fast enumeration you need to convert the PBArray type (basically a typed c buffer) to an array of NSObjects that it represents - either the NSNumber or protobuf message of the objects. You can see an example of the updated fast enumeration code in this change: . You could also add a category for that on PBArray called toObjects.

I just mark the generated code with -fno-objc-arc, but you can get arc and 2.5 support from the booyah pull requests.

The directions are pretty good for setup, but if people want more explicit instructions on the category I use, how I built the protobuf-objc plugin, how to get support for Class prefixes (e.g. IXMyProtoMessage instead of MyProtoMessage) or how I generate the code let me know and I'll try to set aside time to write up a post. I'm using it with > 50 proto files with a lot of cross project dependencies.

A weakness of the library is that it doesn't include the typical Protobuf reflection api on the generated code so doing something like converting a message to a NSDictionary would have to do some hacky stuff with the objC runtime (the code doesn't follow typical KV compliance) or write a custom code generator from protos that do have the reflection api (I did this with python + jinja2). Or - better yet and of similar difficulty, add reflection apis to the code generator ;).

@Richard Topchii 2019-03-04 14:17:49

Could you please share your extension on how to convert PBArray to NSArray?

@Tushar Koul 2013-03-06 11:41:57

EDIT : I had answered this earlier but was deleted by moderator. So I have included some code from the tutorial.

A tutorial which is almost same as the answer posted above - Using Google Protocol Buffers in Objective-C on iOS and the Mac

Follow the steps given in learnvst's answer, and refer the comments for pitfalls. I followed the exact same steps except for

add the directory of google headers to your additional include directories I added the src/ directory in the header search paths, instead of the google directory.

Also, when i did #import xyz.pb.h the project wasn't building. When I renamed my .m file to .mm i was able to build. This point is mentioned in the tutorial very subtly :P.

Basically, any .m file which is importing a any .pb.h file, should be renamed with extension .mm

Here's some content from the tutorial -


package kotancode;

enum ZombieType {
    SLOW = 0;
    FAST = 1;

message ZombieSighting {
    required string name = 1;
    required double longitude = 2;
    required double latitude = 3;
    optional string description = 4;
    required ZombieType zombieType = 5 [default = SLOW];


// -- ZombieSightingMessage.h - note my C++ object is not in the public interface.
#import <Foundation/Foundation.h>

@interface ZombieSightingMessage : NSObject
- (void)doSomething;

// --
#import <UIKit/UIKit.h>
#import "ZombieSightingMessage.h"
#import "zombie.pb.h"

@implementation ZombieSightingMessage

- (void)doSomething {
    // Doing random stuff with a UIView here to show the mixing
    // of C++ and Objective-C/Cocoa syntax in the same file...
    UIView *uiView = [[UIView alloc] init];
    [uiView setCenter:CGPointMake(20, 10)];

    // instantiate my protobuf-generated C++ class.
    kotancode::ZombieSighting *zombieSighting = new kotancode::ZombieSighting();
    zombieSighting->set_description("This is a zombie");

    // Some small tomfoolery required to go from C++ std::string to NSString.
    std::string x = zombieSighting->DebugString();
    NSString *output = [NSString stringWithCString:x.c_str() encoding:[NSString defaultCStringEncoding]];
    NSLog(@"zombie: %@", output);

    // Instantiate another zombie from the previous zombie's raw bytes.
    NSData *rawZombie = [self getDataForZombie:zombieSighting];
    kotancode::ZombieSighting *otherZombie = [self getZombieFromData:rawZombie];

    // Dump the second zombie so we can see they match identically...
    NSString *newOutput = [NSString stringWithCString:otherZombie->DebugString().c_str() encoding:[NSString defaultCStringEncoding]];
    NSLog(@"other zombie: %@", newOutput);

    // Grimace all you want, but this is C++ and we need to clean up after ourselves.


// Serialize to NSData. Note this is convenient because
// we can write NSData to things like sockets...
- (NSData *)getDataForZombie:(kotancode::ZombieSighting *)zombie {
    std::string ps = zombie->SerializeAsString();
    return [NSData dataWithBytes:ps.c_str() length:ps.size()];

// De-serialize a zombie from an NSData object.
- (kotancode::ZombieSighting *)getZombieFromData:(NSData *)data {
    int len = [data length];
    char raw[len];
    kotancode::ZombieSighting *zombie = new kotancode::ZombieSighting;
    [data getBytes:raw length:len];
    zombie->ParseFromArray(raw, len);
    return zombie;


EDIT : I am using Xcode 4.5. Even after I followed all the steps I was getting a linker error.

symbols not found for architecture i386

Due to this I couldnt run the code on simulator. But it worked on actual device

@Ted Tomlinson 2013-08-06 20:31:09

This is a great post, but I'm curious why people wouldn't want to use the booyah port (based on metasyntactic)? It gives you Objc objects so your view code doesn't have to worry about having c++ objects with different notation and manually free memory (if using arc)? Is is a protobuf version thing? do you need the reflection api that c++ provides? I'm using the booyah port in multiple projects and it's worked great so far...

@Tushar Koul 2013-08-07 04:54:30

I was facing problem compiling protos with "repeated" variables.

@Tushar Koul 2013-08-07 04:57:27

@Ted pls post the link of the library you are using.

@AlBeebe 2014-01-30 19:47:58

I also ran into the "repeated" variables bug like @TusharKoul which means i have to utilize this c++ code.

@Tushar Koul 2014-01-31 05:56:15

@AlBeebe did you try compiling the code from booyah repo that Ted posted?

Related Questions

Sponsored Content

14 Answered Questions

[SOLVED] Biggest differences of Thrift vs Protocol Buffers?

1 Answered Questions

1 Answered Questions

[SOLVED] Protocol Buffer for Objective-C

1 Answered Questions

[SOLVED] Difference in .NET Protocol Buffer libraries

Sponsored Content