19

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

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

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

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

4

4 に答える 4

19

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

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

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>_stringprintf.cc
  • 以下の手順に注意深く従ってください。すべて正常に動作するはずです。

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

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

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

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

ここに画像の説明を入力してください

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

}
于 2012-04-23T11:29:15.300 に答える
14

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

pod 'GoogleProtobuf', '~> 2.5.0'

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

于 2013-10-19T19:19:18.123 に答える
12

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

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

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

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

また、私が行っ#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

編集:私はXcode4.5を使用しています。すべての手順を実行した後でも、リンカーエラーが発生していました。

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

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

于 2013-03-06T11:41:57.980 に答える
2

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

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

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

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

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

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

于 2013-08-07T18:45:45.180 に答える