是 iOS 的元语法静态库。. .
http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers
. . . 与常规的旧 C++ 编译的原型文件兼容吗?我不想使用生成 Obj-C 的捆绑编译器。
有没有办法编译谷歌为 iOS 提供的库?
是 iOS 的元语法静态库。. .
http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers
. . . 与常规的旧 C++ 编译的原型文件兼容吗?我不想使用生成 Obj-C 的捆绑编译器。
有没有办法编译谷歌为 iOS 提供的库?
好的。在这种情况下,元句法库(或任何其他第 3 方库)似乎是不必要的。您可以直接将 Google 源代码添加到您的项目中。我在 google 讨论组中找到了 Nicola Ferruzzi 的以下答案。. .
原来的答案在这里。. .
http://groups.google.com/group/protobuf/browse_thread/thread/ca4218d7db144252
该答案的内容包含在下面的图像中,以永久记录...
编辑
由于今晚第一次尝试这个,除了下面列出的步骤之外,我还需要几个步骤(这适用于 protobuf 2.5.0)。
find . -name "*unittest*" -exec rm -rf {} \;
testing
#include <google/protobuf/testing/googletest.h>
_stringprintf.cc
我在我的应用程序中使用最新版本.. 如果您熟悉 C++,您实际上并不需要 objc 直接支持,只有一点您必须从 std::string 传递到 NSData,反之亦然。它非常简单。
编译和测试我发现的最简单的方法是在我自己的项目中导入整个 google 目录:) (第二次你可以制作自己的框架,但为了测试这个过程就可以了)
- 下载最新版本
- 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; }
您可以通过将以下行添加到您的 Podfile 中,为使用 Cocoapods 的 Xcode 5 项目添加对 Google Protocol Buffers 的支持。
pod 'GoogleProtobuf', '~> 2.5.0'
这会将 C++ 版本的 protobuf 代码放入项目的 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++,然后作为构建的一部分进行编译。
编辑:我之前回答过这个问题,但被版主删除了。所以我已经包含了教程中的一些代码。
与上面发布的答案几乎相同的教程 -在 iOS 和 Mac 上的 Objective-C 中使用 Google 协议缓冲区
按照 learnvst 的答案中给出的步骤,并参考评论中的陷阱。我遵循完全相同的步骤,除了
将 google 标头目录添加到您的附加包含目录 我在标头搜索路径中添加了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提供的本机 Obj 代码生成的略微修改版本
它支持开箱即用的重复字段,但为了使用 ObjC 快速枚举,您需要将 PBArray 类型(基本上是类型化的 c 缓冲区)转换为它所代表的 NSObject 数组——对象的 NSNumber 或 protobuf 消息。您可以在此更改中看到更新的快速枚举代码示例:。您还可以在 PBArray 上添加一个名为 toObjects 的类别。
我只是用 标记生成的代码,但您可以从booyah 拉取请求-fno-objc-arc
中获得 arc 和 2.5 支持。
这些说明非常适合设置,但如果人们想要更明确地说明我使用的类别、我如何构建 protobuf-objc 插件、如何获得对类前缀的支持(例如 IXMyProtoMessage 而不是 MyProtoMessage)或我如何生成代码让我知道,我会尽量腾出时间写一篇文章。我将它与> 50个具有很多跨项目依赖关系的原型文件一起使用。
该库的一个弱点是它在生成的代码中不包含典型的 Protobuf 反射 api,因此执行诸如将消息转换为 NSDictionary 之类的操作将不得不对 objC 运行时做一些骇人听闻的事情(代码不遵循典型的KV 合规性)或从具有反射 api 的 protos 编写自定义代码生成器(我使用 python + jinja2 完成了此操作)。或者 - 更好和类似的困难,将反射 API 添加到代码生成器;)。