【问题标题】:Google protocol buffers on iOSiOS 上的 Google 协议缓冲区
【发布时间】:2012-05-03 21:20:45
【问题描述】:

是 iOS 的元语法静态库。 . .

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

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

有没有什么方法可以编译谷歌为 iOS 提供的库?

【问题讨论】:

    标签: c++ ios protocol-buffers


    【解决方案1】:

    好的。在这种情况下,元语法库(或任何其他第 3 方库)似乎是不必要的。您可以直接将 Google 源代码添加到您的项目中。我在 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的文件夹
    • stringprintf.cc 中注释掉#include <google/protobuf/testing/googletest.h>
    • 现在请仔细按照以下说明进行操作,一切正常。

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

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

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

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

    然后你可以使用 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; 
    
    }
    

    【讨论】:

    • 当您说“将 google 标头的目录添加到您的其他包含目录”时,这是什么意思?将其添加到标题搜索路径?
    • 在 XCode 中,这意味着将其添加到标题搜索路径中,是的。不同的编译器 IDE 会有不同的标签。一切顺利。
    • 如果有人关注此问题并遇到无法找到 的问题,请删除 config.h 中的“tr1”。另外,如果编译失败message.cc,在message.cc文件中添加include <iostream>
    • 按照此处提供的一般说明,我构建了一个 Cocoapod,它直接从 Google tar.gz 文件安装 Google Protobuf v2.5.0。它适用于 Xcode 5 并以 iOS 7 为目标。它还包括为 Mac OS 构建的 protoc 编译器,因此可以将 Protobuf 支持添加到项目中而无需额外的麻烦。 podspec 在主要的 Cocoapods Specs 存储库中。只需“pod search protobuf”即可找到它。
    • 好的,我找到了。 C++语言方言必须设置为C++11,标准库设置为libc++。
    【解决方案2】:

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

    pod 'GoogleProtobuf', '~> 2.5.0'
    

    这会将 C++ 版本的 protobuf 代码放入项目的 Pod 中。它还将在您的项目中的文件夹Pods/GoogleProtobuf/bin/protoc 中添加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++,然后作为构建的一部分进行编译。

    【讨论】:

    【解决方案3】:

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

    我正在使用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)或者我如何生成代码让我知道,我会尽量留出时间来写一篇文章。我将它与超过 50 个具有大量跨项目依赖项的 proto 文件一起使用。

    该库的一个弱点是它在生成的代码中不包含典型的 Protobuf 反射 api,因此执行诸如将消息转换为 NSDictionary 之类的操作将不得不对 objC 运行时做一些骇人听闻的事情(代码没有t 遵循典型的 KV 合规性)或从具有反射 api 的 protos 编写自定义代码生成器(我使用 python + jinja2 完成了此操作)。或者 - 更好且难度相似的,将反射 API 添加到代码生成器中;)。

    【讨论】:

    • 能否分享一下如何将PBArray 转换为NSArray 的扩展程序?
    【解决方案4】:

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

    一个教程和上面贴的答案几乎一样 - Using Google Protocol Buffers in Objective-C on iOS and the Mac

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

    将 google headers 的目录添加到您的附加包含目录中 我在标题搜索路径中添加了 src/ 目录,而不是 google 目录。

    另外,当我做#import xyz.pb.h 时,项目还没有建立。当我将我的 .m 文件重命名为 .mm 时,我能够构建。这一点在教程中很巧妙地提到了: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。即使在我按照所有步骤操作之后,我仍然收到链接器错误。

    找不到架构 i386 的符号

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

    【讨论】:

    • 这篇文章很棒,但我很好奇为什么人们不想使用 booyah 端口(基于元句法)?它为您提供了 Objc 对象,因此您的视图代码不必担心具有不同表示法的 c++ 对象和手动释放内存(如果使用 arc)?是protobuf版本的东西吗?你需要c++提供的反射api吗?我在多个项目中使用 booyah 端口,到目前为止效果很好......
    • 我在编译带有“重复”变量的原型时遇到了问题。
    • @Ted 请张贴您正在使用的图书馆的链接。
    • 我还遇到了像 @TusharKoul 这样的“重复”变量错误,这意味着我必须使用这个 c++ 代码。
    • @AlBeebe 您是否尝试从 Ted 发布的 booyah 存储库中编译代码?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 2014-03-13
    • 1970-01-01
    • 2011-10-18
    相关资源
    最近更新 更多