iOS上的Google协议缓冲区

是iOS的metasyntactic静态库。 。 。

http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers

。 。 。 与常规的旧C ++编译的protofiles兼容? 我不想使用生成Obj-C的捆绑编译器。

有没有什么办法可以编译Google for iOS提供的库?

好。 在这种情况下,似乎是不必要的定义库(或任何其他第三方库)是不必要的。 您可以直接将Google来源添加到您的项目中。 我在谷歌讨论组中findNicola Ferruzzi的以下答案。 。 。

原来的答案在这里。 。 。

http://groups.google.com/group/protobuf/browse_thread/thread/ca4218d7db144252

这个答案的内容包括下面的图像,使永久logging…


编辑

自从今天晚上第一次再次尝试这个之后,除了下面列出的那些之外,我还需要更多的步骤(这与protobuf 2.5.0一起使用)。

  • 你需要链接到libz.dylib。 你可以在Build Phase> Link Binary With Libraries中设置它。
  • 要轻松删除所有与unit testing有关的东西,请使用下面的命令从shell目录中find . -name "*unittest*" -exec rm -rf {} \; google目录find . -name "*unittest*" -exec rm -rf {} \; find . -name "*unittest*" -exec rm -rf {} \;
  • 还要删除名为testing的文件夹
  • stringprintf.cc注释掉#include <google/protobuf/testing/googletest.h>
  • 现在仔细按照下面的说明,所有应该工作正常。

我在我的应用程序中使用最新版本..如果你熟悉C ++,你并不需要objc直接支持,只有一点你必须从std :: string传递给NSData,反之亦然。 而且非常简单。

编译和testing我发现的最简单的方法是只在我自己的项目中导入整个谷歌目录:)(第二次,你可以使自己的框架,但testing此过程只是工作)

  • 下载最新版本
  • 自动configuration和像你只是build立为macosx(你需要命令行工具)。 这样你最终与协议
    二进制和macosx库(你不需要)
  • 打开你的Xcode iOS项目
  • 添加“新文件”到您的项目,并select谷歌目录
  • 将google头文件的目录添加到您的其他包含目录中
  • 将protobuffer src目录中的config.h添加到您的应用程序中
  • 从谷歌组删除一切包含unitest 🙂
  • 从谷歌组删除编译器和Java的东西;

您应该能够编译没有任何链接错误。 给你一个想法,这是我直接编译

在这里输入图像说明

然后你可以使用protoc为你的协议生成c ++源文件。 要用objc来使用它们,你必须重命名你的源文件为“mm”,那么你可以做类似的事情

要序列化到NSDATA

让我们说你的消息被称为数据包

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

阅读NSDATA

 - (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; } 

编辑 :我已经回答了这个较早,但被主持人删除。 所以我已经包含了教程中的一些代码。

这个教程与上面的答案几乎相同 – 在iOS和Mac上使用Objective-C中的Google协议缓冲区

按照learnvst的答案给出的步骤,并参考评论中的陷阱。 我遵循完全相同的步骤,除了

将google头文件的目录添加到您的其他包含目录中。我在头文件searchpath中添加了src /目录,而不是google目录。

另外,当我做#import xyz.pb.h项目不是build设。 当我将我的.m文件重命名为.mm时,我能够构build。 这一点在教程中提到很微妙:P。

基本上,任何导入任何.pb.h文件的.m文件都应该用扩展名.mm重命名

以下是教程中的一些内容 –

原始文件

 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

 // -- ZombieSightingMessage.h - note my C++ object is not in the public interface. #import <Foundation/Foundation.h> @interface ZombieSightingMessage : NSObject - (void)doSomething; @end 

ZombieSightingMessage.mm

 // -- ZombieSightingMessage.mm #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_name("Kevin"); zombieSighting->set_description("This is a zombie"); zombieSighting->set_latitude(41.007); zombieSighting->set_longitude(21.007); zombieSighting->set_zombietype(kotancode::ZombieType::FAST); // 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. free(zombieSighting); free(otherZombie); } // 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; } @end 

编辑 :我正在使用Xcode 4.5。 即使我遵循所有的步骤后,我得到一个链接器错误。

符号未findbuild筑i386

由于这个我不能在模拟器上运行的代码。 但它在实际的设备上工作

您可以通过将以下行添加到您的Podfile,将使用Cocoapods的Google Protocol Buffers支持添加到Xcode 5项目中。

 pod 'GoogleProtobuf', '~> 2.5.0' 

这将把C ++版本的protobuf代码放到你的项目的Pod中。 它还会将Pods/GoogleProtobuf/bin/protoc编译器添加到项目中的文件夹Pods/GoogleProtobuf/bin/protoc

您可以在项目中创build自定义构build规则,自动将.proto文件转换为.ph.{h,cc}文件。 这是我如何做到这一点:

将生成规则设置为“处理名称匹配的源文件:* .proto使用自定义脚本”。 该脚本应该包括以下内容:

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

设置输出文件以包含以下内容:

 $(INPUT_FILE_DIR)/cpp/$(INPUT_FILE_BASE).pb.h $(INPUT_FILE_DIR)/cpp/$(INPUT_FILE_BASE).pb.cc 

您包含在项目中的任何.proto文件现在都会自动转换为C ++,然后作为构build的一部分进行编译。

我猜根据实际的问题,我的评论是值得发布作为答案:

我正在使用由Booyah提供的本地Obj代码的一个稍微修改版本

它支持开箱即用的重复字段,但为了使用ObjC快速枚举,您需要将PBArraytypes(基本上是一个types化的c缓冲区)转换为它所表示的NSObject的数组 – 无论是对象的NSNumber还是protobuf消息。 您可以在此更改中看到更新的快速枚举代码示例:。 您也可以在PBArray上添加一个名为toObjects的类别。

我只用-fno-objc-arc标记生成的代码,但是你可以从booyah pull请求中得到arc和2.5的支持。

这个方向对于设置来说是相当不错的,但是如果人们想在我使用的类别上有更明确的说明,我是如何构buildprotobuf-objc插件的,如何获得对类前缀的支持(例如IXMyProtoMessage而不是MyProtoMessage)或者如何生成代码让我知道,我会尽量留出时间写一篇文章。 我使用它与大量的交互项目依赖项> 50个原始文件。

该库的一个弱点是,它不包括生成的代码上典型的Protobufreflectionapi,所以做一些类似于将消息转换为NSDictionary的东西,将不得不用objC运行时做一些hacky的东西(代码不符合典型KV合规性),或者从protos写一个自定义代码生成器,这些原生代码有reflectionapi(我用python + jinja2做了这个)。 或者 – 更好,但是具有相似的难度,将代码生成器添加到代码生成器;)。