web-dev-qa-db-ja.com

iOS上のGoogleプロトコルバッファ

IOS用のメタ構文静的ライブラリです。 。 。

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

。 。 。通常の古いC++コンパイル済みプロトファイルと互換性がありますか?私はnotObj-Cを生成するバンドルコンパイラを使用したいと思います。

Google for iOSが提供するライブラリをコンパイルする方法はありますか?

18
learnvst

OK。この場合、メタ構文ライブラリ(またはその他のサードパーティライブラリ)は不要のようです。 Googleソースをプロジェクトに直接追加するだけです。私はグーグルディスカッショングループでニコラFerruzziから次の答えを見つけました。 。 。

元の答えはここにあります。 。 。

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

この回答の内容は、永続的な記録を作成するための画像とともに以下に含まれています...


[〜#〜]編集[〜#〜]

今夜、久しぶりにこれを再試行したので、以下に概説する手順に加えて、さらにいくつかの手順が必要でした(これはprotobuf 2.5.0で機能します)。

  • Libz.dylibに対してリンクする必要があります。これは、[ビルドフェーズ]> [バイナリとライブラリのリンク]で設定します。
  • 単体テストに関連するものをすべて簡単に削除するには、Googleディレクトリのシェルから次のコマンドを使用しますfind . -name "*unittest*" -exec rm -rf {} \;
  • testingというフォルダも削除します
  • コメントアウト#include <google/protobuf/testing/googletest.h> in stringprintf.cc
  • 以下の手順に注意深く従ってください。すべて正常に動作するはずです。

私は私のアプリで最新バージョンを使用しています..C++に精通している場合は、objcの直接サポートは本当に必要ありません。std:: stringからNSDataおよびその逆に渡す必要があるポイントは1つだけです。そして、その非常に簡単です。

私が見つけた最も簡単な方法をコンパイルしてテストするには、Googleディレクトリ全体を自分のプロジェクトにインポートするだけです:)(2回目は独自のフレームワークを作成できますが、この手順をテストするために機能します)

  • 最新バージョンをダウンロード
  • autogenは、macosx用にビルドしたように構成および作成します(コマンドラインツールが必要です)。このようにして、protocになります
    バイナリとmacosx用のライブラリ(必要ありません)
  • xcodeiOSプロジェクトを開きます
  • プロジェクトに「新しいファイル」を追加し、Googleディレクトリを選択します
  • googleヘッダーのディレクトリを追加のインクルードディレクトリに追加します
  • protobuffersrcディレクトリからアプリにconfig.hを追加します
  • グーグルグループからunitestを含むすべてを削除します:)
  • グーグルグループからコンパイラとJavaもの;

リンクエラーなしでコンパイルできるはずです。あなたにアイデアを与えるために、これは私が直接コンパイルするものです

enter image description here

次に、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; 

}
19
learnvst

Podfileに次の行を追加することで、Cocoapodsを使用してXcode5プロジェクトにGoogleProtocolBuffersのサポートを追加できます。

pod 'GoogleProtobuf', '~> 2.5.0'

これにより、C++バージョンのprotobufコードがプロジェクトのポッドに配置されます。また、プロジェクト内の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++に変換され、ビルドの一部としてコンパイルされます。

14
Bennett Smith

[〜#〜]編集[〜#〜]:以前に回答しましたが、モデレーターによって削除されました。だから私はチュートリアルからいくつかのコードを含めました。

上記の回答とほぼ同じチュートリアル--- iOSおよびMacのObjective-CでGoogle Protocol Buffersを使用

Learnvstの回答に記載されている手順に従い、落とし穴についてコメントを参照してください。私はまったく同じ手順に従いましたが、

googleヘッダーのディレクトリを追加のインクルードディレクトリに追加しますヘッダーにsrc /ディレクトリを追加しましたGoogleディレクトリの代わりに検索パス。

また、私がしたとき#import xyz.pb.hプロジェクトは構築されていませんでした。 。mファイルの名前を。mmに変更すると、ビルドします。この点は、チュートリアルで非常に微妙に言及されています:P。

基本的に、any。pb.hをインポートしているany。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

[〜#〜] edit [〜#〜]:Xcode4.5を使用しています。すべての手順を実行した後でも、リンカーエラーが発生していました。

アーキテクチャi386のシンボルが見つかりません

このため、シミュレーターでコードを実行できませんでした。しかし、それは実際のデバイスで動作しました

12
Tushar Koul

実際の質問に基づいて、私のコメントは回答として投稿する価値があると思います。

Booyah によって提供されるネイティブObjコード生成のわずかに変更されたバージョンを使用しています

箱から出して繰り返されるフィールドをサポートしますが、ObjC高速列挙を使用するには、PBArrayタイプ(基本的には型付きcバッファー)をそれが表すNSObjectの配列(オブジェクトのNSNumberまたはprotobufメッセージ)に変換する必要があります。更新された高速列挙コードの例は、 この変更 :で確認できます。 toObjectsと呼ばれるカテゴリをPBArrayに追加することもできます。

生成されたコードを-fno-objc-arcでマークするだけですが、 booyah pull requests からarcと2.5のサポートを得ることができます。

指示はセットアップにはかなり適していますが、使用するカテゴリ、protobuf-objcプラグインの構築方法、クラスプレフィックスのサポートの取得方法(MyProtoMessageではなくIXMyProtoMessageなど)、またはコードの生成方法について、より明確な指示が必要な場合は、私に知らせてください、そして私は投稿を書くために時間を取っておこうとします。プロジェクト間の依存関係が多い50を超えるプロトファイルで使用しています。

ライブラリの弱点は、生成されたコードに典型的なProtobufリフレクションAPIが含まれていないことです。そのため、メッセージをNSDictionaryに変換するようなことを行うには、objCランタイムでハッキーな処理を行う必要があります(コードは典型的なものに従わない) KV準拠)またはリフレクションAPIを備えたプロトからカスタムコードジェネレーターを作成します(これはpython + jinja2)で行いました)。または-さらに良いことに、同様の難しさで、リフレクションAPIを追加します。コードジェネレーター ;)。

1
Ted Tomlinson