2012-11-13 7 views
6

iOSプロジェクトでプロトコルバッファを使いたいです。プロジェクト全体をObjective-C++の失敗にするのを避けようとしているので、Objective-CのクラスにC++のprotobufクラスをラップしたいと思います。私は数十のprotobufメッセージを持っています。一度に1つのクラスを正常に実行している間は、繰り返しコードを最小限に抑えるために継承を使用したいと思っています。私はObjective-Cを初めて使っています.10年後にC++について知っていることを少しも使っていないので、これはほとんどが欲求不満の練習です。以下は、1つのメッセージをどのようにラップしたかの例です。Objective-Cにプロトコルバッファをラップし、引き続き継承を利用する方法はありますか?

コード

.proto:

message MessageA { 
    optional string value = 1; 
} 

MessageAWrapper.h:

#import <Foundation/Foundation.h> 

@interface MessageAWrapper : NSObject 

@property (nonatomic) NSString *value; 

+ (id)fromString:(NSString *)string; 
- (NSString *)serialize; 

@end 

MessageAWrapper.mm:

#import "MessageA.h" 
#import "message.pb.h" 

@interface MessageAWrapper() 

@property (nonatomic) MessageA *message; 

@end 

@implementation MessageAWrapper 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     self.message = new MessageA(); 
    } 
    return self; 
} 

- (void)dealloc { 
    delete self.message; 
    self.message = NULL; 
} 

- (NSString *)value { 
    return [NSString stringWithUTF8String:self.message->value().c_str()]; 
} 

- (void)setValue:(NSString *)value { 
    self.message->set_value([value UTF8String]); 
} 

- (NSString *)serialize { 
    std::string output; 
    self.message->SerializeToString(&output); 
    return [NSString stringWithUTF8String:output.c_str()]; 
} 

+ (id)fromString:(NSString *)string { 
    MessageA *message = new MessageA(); 
    message->ParseFromString([string UTF8String]); 

    MessageAWrapper *wrapper = [[MessageAWrapper alloc] init]; 
    wrapper.message = message; 
    return wrapper; 
} 

@end 

ゴール

だけ変動が包まれたクラス型( initdeallocserializefromString)ので、理想的に私はそれを上に置くしたいとした何十回も繰​​り返され、ここで多くのコードがあり

代わりに親のProtobufMesssageクラス。残念ながら、親クラスが子供が使用しているクラスを知る方法を見つけることができないので、私はこの作業を成功させることができませんでした。例えば、initfromStringが必要です。私は

    が発生しました

    • 構造体
    • テンプレートクラス
    • void *型

    障害物をしようとしました

    物事

  • クラス/タイプ
  • .Hファイル内の任意のC++ヘッダまたはコードを持つことができない(これは、Objective-Cのことがプロジェクト全体を必要と++)
  • への参照を格納するための方法を見つけることができません彼らは私がC++やObjective-Cのはほとんど理解していると述べたよう

抽象的であるためいるProtobufメッセージの両親(MessageまたはMessageLite)への参照を維持する難しさ。私の経験のほとんどは、PythonやJava(ポインタのような基本的なC言語のことはほとんど理解していますが)のようなより高水準の言語を使用しています。

が、これはおそらくないでも可能ですか?私はそれに近づいているか、何かが明らかでないか?どんな助けでも大歓迎です。ありがとう。

答えて

0

私はすべてC++についてはあまり知りませんが、あなたはMessage *するObjective-Cのプロパティを宣言することはできませんか?

既に.mmファイルのプロパティを宣言してヘッダーからC++コードを分離していますが、問題はコンパイラ(value()set_value())によって指定されたインスタンスメソッドであり、サブクラス。フィールドを名前で取得および設定するには、Reflectionクラスを使用すると便利です。ここではこれを示すGoogleのmessage.hからの抜粋です:

Message* foo = new Foo; 
const Descriptor* descriptor = foo->GetDescriptor(); 

const FieldDescriptor* text_field = descriptor->FindFieldByName("text"); 
assert(text_field != NULL); 
assert(text_field->type() == FieldDescriptor::TYPE_STRING); 
assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL); 

const Reflection* reflection = foo->GetReflection(); 
assert(reflection->GetString(foo, text_field) == "Hello World!"); 

あなたがです。TypeCheckのObjective-C -objectForKey:-setObject:forKey:インスタンスメソッドを作成し、値を取得または設定することができ(紛らわしい、MessageAWrapperの場合、キーは@"value"だろう) 。あなたのサブクラスは、C++コードを意識する必要はありません。

-init+fromString:メソッドの作成者機能を、+_createNewInstanceのように区切ることもできます。 C++オブジェクトの作成以外のすべてのコードを再利用するためにMessageWrapperのあなたのサブクラスを可能

+(Message*)_createNewInstance{ return new MessageA(); } 

0

Objective Cは非常に強力な機能検査機能を備えていますが、C++はより限定されています。 RTTI(実行時のタイプ情報)がありますが、それはObjective Cのカウンターパートほど強力ではありません。

ただし、十分かもしれません。あなたのObjective C++クラスの中で、あなたがあなたのタイプのtypeid演算子とメッセージオブジェクトを見つけるかもしれない:

if((typeid(self.message) == typed(foo)){ 
    //doSomething 
else if((typeid(self.message) == typed(bar)){ 
    // doSomething else 
} 

をたぶん最良のオプションは、別の間接レベルを追加することです。すべてのプロトコルバッファC++クラスをラップし、それらのクラスを使用する別のObjective Cを作成するObjective Cクラス階層を作成します(代理人のように)。私はこれがより良い選択肢かもしれないと信じています。やむを得ない事例の場合にのみC++を使用してください。

幸運を祈る!

+0

'dynamic_cast'を使用する方が良いでしょう – newacct

関連する問題