iOS上的Google协议缓冲区

时间:2012-04-23 09:01:59

标签: c++ ios protocol-buffers

是适用于iOS的metasyntactic静态库。 。 。

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

。 。 。兼容常规的旧C ++编译的原型文件?我 想要使用生成Obj-C的捆绑编译器。

有没有办法编译Google for iOS提供的库?

4 个答案:

答案 0 :(得分:19)

确定。在这种情况下,似乎不需要metasyntactic库(或任何其他第三方库)。您只需将Google源代码直接添加到项目中即可。我在谷歌讨论组中找到了Nicola Ferruzzi的以下答案。 。

原来的答案就在这里。 。 。

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

此答案的内容包含在下面,图片可以作为永久记录...


修改

自从今晚第一次再次尝试这个以来,除了下面列出的步骤之外,我还需要更多的步骤(这适用于protobuf 2.5.0)。

  • 您需要链接libz.dylib。你在Build Phases>中设置了它。 Link Binary with Libraries。
  • 要轻松删除所有与单元测试相关的内容,请使用google目录find . -name "*unittest*" -exec rm -rf {} \;中的shell中的以下命令
  • 同时删除名为testing
  • 的文件夹
  • #include <google/protobuf/testing/googletest.h>
  • 中注明stringprintf.cc
  • 现在请仔细按照以下说明操作,一切正常。

  

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

     

编译和测试我发现的最简单方法就是导入   在我自己的项目中的整个谷歌目录:)(第二次你可以   制作你自己的框架但是为了测试这个程序就行了)

     
      
  • 下载最新版本
  •   
  • autogen配置和make就像你刚刚为macosx构建(你需要命令行工具)。这样你最终会使用protoc   二进制文件和macosx库(你不需要)
  •   
  • 打开您的Xcode iOS项目
  •   
  • 将“新文件”添加到您的项目并选择google目录
  •   
  • 将google标头的目录添加到其他包含目录
  •   
  • 将config.h从protobuffer src目录添加到您的应用
  •   来自google群组的
  • 删除包含unitest :)的所有内容。
  •   来自google群组的
  • 删除编译器和java的东西;
  •   
     

您应该能够在没有任何链接错误的情况下进行编译。为你带来   这是我直接编译的想法

     

enter image description here

     

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

     

切换到NSDATA

     

假设您的邮件名为Packet

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

}

答案 1 :(得分:14)

您可以使用Cocoapods将对Google协议缓冲区的支持添加到Xcode 5项目中,方法是将以下行添加到您的Podfile中。

pod 'GoogleProtobuf', '~> 2.5.0'

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

您可以在项目中创建自定义构建规则,自动将.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 ++,然后作为构建的一部分进行编译。

答案 2 :(得分:12)

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

与上面发布的答案几乎相同的教程 - Using Google Protocol Buffers in Objective-C on iOS and the Mac

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

  

将google标头目录添加到其他包含目录中   我在标题搜索路径中添加了 src / 目录,而不是google目录。

此外,当我#import xyz.pb.h时,项目没有建成。当我将 .m 文件重命名为 .mm 时,我能够构建。本教程中非常巧妙地提到了这一点:P。

  

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

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

PROTO文件

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。即使我按照所有步骤操作,我也会收到链接器错误。

  

未找到架构i386的符号

由于这个原因,我无法在模拟器上运行代码。但它适用于实际设备

答案 3 :(得分:1)

我想根据实际问题,我的评论值得张贴作为答案:

我正在使用由Booyah

提供的本机Obj代码生成的略微修改版本

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

我只是使用-fno-objc-arc标记生成的代码,但您可以从booyah pull requests获得arc和2.5支持。

方向非常适合设置,但是如果人们想要更明确的指示我使用的类别,我如何构建protobuf-objc插件,如何获得对类前缀的支持(例如IXMyProtoMessage而不是MyProtoMessage)或者我如何生成代码让我知道,我会尽量留出时间写一篇文章。我正在使用&gt; 50个具有大量跨项目依赖关系的proto文件。

库的一个弱点是它不包含生成的代码上典型的Protobuf反射API,所以做一些事情就像将消息转换为NSDictionary一样,必须用objC运行时做一些hacky的东西(代码没有'遵循典型的KV合规性)或者从具有反射api的protos编写自定义代码生成器(我使用python + jinja2执行此操作)。或者 - 更好的和类似的难度,将反射apis添加到代码生成器;)。