私は今日退屈で、C++/Obj-C補間法を使いこなすことに決めました。とても面白いセットアップを作成する方法を見つけました。Objective-C - C++によるブリッジングの短所?
@protocol NSCPPObj <NSObject>
-(id) init;
-(id) initWithInt:(int) value;
-(int) somethingThatReturnsAValue;
-(void) doSomething;
@end
class NSCPPObj : objc_object {
public:
static Class cls();
int iVar;
NSCPPObj();
NSCPPObj(int);
int somethingThatReturnsAValue();
void doSomething();
};
ご覧のとおり、インターフェイスはかなりわかりやすく分かりやすいです。 C++オブジェクト用とObj-Cプロトコル用の2つ(ほぼ同じ)のインタフェースを作成します。
は今、私はこれを実装する方法を見つけましたが、自分自身を引き締める、これは醜い取得します。
// NSCPPObj.mm
#import <objc/runtime.h>
#import <iostream>
#import "NSCPPObject.h"
Class NSCPPObj_class = nil;
__attribute__((constructor))
static void initialize()
{
NSCPPObj_class = objc_allocateClassPair([NSObject class], "NSCPPObj", 0);
class_addMethod(NSCPPObj_class->isa, @selector(alloc), imp_implementationWithBlock(^(id self) {
return class_createInstance(NSCPPObj_class, sizeof(struct NSCPPObj));
}), "@@:");
class_addMethod(NSCPPObj_class, @selector(init), imp_implementationWithBlock(^(id self) {
return self;
}), "@@:");
class_addMethod(NSCPPObj_class, @selector(initWithInt:), imp_implementationWithBlock(^(id self, int value) {
((struct NSCPPObj *) self)->iVar = value;
return self;
}), "@@:i");
class_addMethod(NSCPPObj_class, @selector(doSomething), imp_implementationWithBlock(^(id self) {
((struct NSCPPObj *) self)->doSomething();
}), "[email protected]:");
class_addMethod(NSCPPObj_class, @selector(somethingThatReturnsAValue), imp_implementationWithBlock(^(id self) {
return ((struct NSCPPObj *) self)->somethingThatReturnsAValue();
}), "[email protected]:");
objc_registerClassPair(NSCPPObj_class);
}
Class NSCPPObj::cls()
{
return NSCPPObj_class;
}
NSCPPObj::NSCPPObj()
{
this->isa = NSCPPObj_class;
[((id<NSCPPObj>) this) init];
}
NSCPPObj::NSCPPObj(int value)
{
this->isa = NSCPPObj_class;
[((id<NSCPPObj>) this) initWithInt:value];
}
void NSCPPObj::doSomething()
{
std::cout << "Value Is: " << [((id<NSCPPObj>) this) somethingThatReturnsAValue] << std::endl;
}
int NSCPPObj::somethingThatReturnsAValue()
{
return iVar;
}
私はこれが何をするか要約します:
- は、クラスペア
- を割り当てすべてのクラスメソッドとインスタンスメソッドをオブジェクトに追加します
- クラスペアを登録します
あなたが見ることができるように今、これは非常に柔軟ではないが、それは仕事をし、そしてそれは、双方向の通りです:
id<NSCPPObj> obj = [[NSCPPObj::cls() alloc] initWithInt:15];
[obj doSomething];
NSLog(@"%i", [obj somethingThatReturnsAValue]);
NSLog(@"%@", obj);
NSCPPObj *objAsCPP = (__bridge NSCPPObj *) obj;
objAsCPP->doSomething();
std::cout << objAsCPP->somethingThatReturnsAValue() << std::endl;
あなたはまたnew NSCPPObj(15)
を使用して、オブジェクトを作成し、それに覚えることができます消して! 明らかに、これはARC環境または非ARC環境では機能しますが、ARCではいくつかの余分なブリッジキャストが必要です。
私は本当の質問になります:
このデザイン構造の長所と短所は何ですか?私は私の頭の上のオフ数を一覧表示することができます。
長所:
- にObjC
- との結合C++
- 動的メソッドのオーバーロード演算子は、C++またはにObjCのファッションのいずれかで構築することができます
短所:
- 読みにくい実装
- セレクタ&バインディングは、すべてのC++実装のために追加する必要があります
- Classオブジェクトが直接
ので参照することはできませんインターフェースに追加、すべてのことの後、あなたがこれをお勧めしますアプリケーションの設計構造と理由。
私はこの良い行く応答を与えるために、あまりにも少しのC++を知っているが、これに対する答えは、あなたが取り組んでいるアプリケーションのまさに種類に依存しているのだろうか。既存のC++ゲームを移植すると、これは単純なユーティリティアプリよりもはるかに役立ちます。シーズニングされたC++プログラマーは、Objective-C指向の人よりも高く評価します。 – lxt
再投票する投票。私はこれがいかに建設的ではないかもしれないのか理解していますが、これはコミュニティサイトです。私はあなたが司会者であることを認識していますが、あなたがこれを閉じることを望んでいる唯一の人であることを見ています。 –
私は司会者ではなく、私はこの質問に審査のためにフラグを立てました。それは話題にならない。 – mydogisbox