这是用于iOS的metasyntactic静态库...
http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers
...是否与常规的C++编译proto文件兼容?我不想使用生成Obj-C的捆绑编译器。
有没有办法编译Google为iOS提供的库?
这是用于iOS的metasyntactic静态库...
http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers
...是否与常规的C++编译proto文件兼容?我不想使用生成Obj-C的捆绑编译器。
有没有办法编译Google为iOS提供的库?
好的。看起来在这种情况下,元语法库(或其他第三方库)是不必要的。您可以直接将Google源代码添加到您的项目中。我在谷歌讨论组中找到了Nicola Ferruzzi的以下答案...
原始答案在这里...
http://groups.google.com/group/protobuf/browse_thread/thread/ca4218d7db144252
这个答案的内容如下,包含图片以便做成永久记录...编辑
今晚再次尝试时,除了下面概述的步骤,我还需要几个步骤(这适用于protobuf 2.5.0)。
find . -name "*unittest*" -exec rm -rf {} \;
testing
的文件夹stringprintf.cc
中注释掉#include <google/protobuf/testing/googletest.h>
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
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
TO SERIALIZE TO NSDATA
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()];
TO READ FROM 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将Google Protocol Buffers的支持添加到Xcode 5项目中。
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++,然后作为构建的一部分进行编译。
编辑:我之前回答了这个问题,但被版主删除了。所以我包含了一些教程中的代码。
一个几乎与上面发布的答案相同的教程 - 在iOS和Mac上使用Google协议缓冲区进行Objective-C编程
按照learnvst的答案给出的步骤,并参考评论中的陷阱。我遵循了完全相同的步骤,除了
将谷歌头文件目录添加到您的其他包含目录中 我在头搜索路径中添加了src/目录,而不是google目录。
此外,当我执行#import xyz.pb.h
时,项目无法构建。当我将我的.m文件重命名为.mm时,我能够构建。这一点在教程中非常微妙:P。
Here's some content from the tutorial -基本上,导入任何.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架构的符号
由于这个原因,我无法在模拟器上运行代码。但它在实际设备上可用。
根据实际问题,我认为我的评论值得发布为答案:
我正在使用稍微修改过的本地Obj代码生成,由Booyah提供。
它支持开箱即用的重复字段,但为了使用ObjC快速枚举,您需要将PBArray类型(基本上是一个有类型的c缓冲区)转换为它表示的NSObject数组 - 要么是NSNumber或对象的protobuf消息。您可以在此更改中查看已更新的快速枚举代码示例:。您还可以在PBArray上添加名为toObjects的类别。
我只是使用-fno-objc-arc
标记生成的代码,但您可以从booyah拉取请求获取ARC和2.5支持。
设置说明非常好,但如果人们想要更明确的说明,例如我使用的类别,如何构建protobuf-objc插件,如何获得Class前缀的支持(例如IXMyProtoMessage而不是MyProtoMessage),或者如何生成代码,请告诉我,我会尝试抽出时间写一篇文章。我正在使用它与> 50个proto文件,具有许多跨项目依赖关系。
该库的一个弱点是它不包括生成的代码上的典型Protobuf反射api,因此执行诸如将消息转换为NSDictionary之类的操作需要使用objC运行时进行一些hacky处理(代码不遵循典型的KV兼容性)或编写自定义代码生成器从具有反射api的protos中(我使用python + jinja2完成了这项工作)。或者 - 更好的方法是并且难度相似,将反射api添加到代码生成器中;)。
PBArray
转换为 NSArray
的扩展程序? - Richard Topchii
config.h
文件中删除'tr1'。此外,如果您无法编译message.cc
,请在message.cc
文件中添加include <iostream>
。 - Tony