2016-08-28 9 views
2

私はいくつかのオブジェクト(ラベル、ボタン..)のプロパティを変更したい、私はC + +のコードのストーリーボードを使用して作成しました。ですから、ViewControllerクラスの内部メソッドを実行する方法が必要です。C++クラスからSwiftオブジェクトにアクセスするには?

これを行う適切な方法はありますか?別の可能性はありますか?

私はコールバックを使用しようとしましたが、ViewControllerクラスのグローバルと内部の間に常にこの障壁があります。前もって感謝します!

EDIT: 私はCの外++コードを迅速クラスにアクセスする方法がわからないので、私は任意の適切な例を与えることはできませんが、私はこの(疑似コード)のようなものを考えた:

でC++:

int main(){ 
    say_hello(); 
} 

とスウィフト中:ここ

class ViewController: NSViewController { 
    @IBOutlet weak var label: NSTextField! 
    func say_hello(){ 
     label.stringValue = "Hello" 
    } 
} 
+2

私はすべての私のSWIFT/C++ Objective-Cの++サンクを介して通信を行います。 –

+0

あなたがここに誰かに遭遇している問題を示す簡単なコードスニペットを提供できれば、あなたを助けることができるかもしれません。 – OmniProg

+0

@OmniProg:役に立つと思われるもの(ヘッダファイルを省略したもの)の例をいくつか追加しましたが、同様の方法で動作するとは思われません。これをアーカイブする方法はありますか? 'event in cpp-class' - >' swift-method'を呼び出す - > 'ラベル値を変更する '(例として)? – archimedes

答えて

1

はこれを行うことができる方法の単純化しすぎている例Richardが提案したObjective-C++ラッパーを使用しています。メモリ管理やスレッドの安全性など、ここでは扱いません。この例では、SwiftインスタンスとC++クラスインスタンスの間に1対1の関係があります。またSwiftオブジェクトポインタは識別子として使用され、どのSwiftオブジェクトが通知を受け取るべきかを決定します。これは危険です。下のコードのコメントを参照してください。 Objective-C++ラッパーのより洗練されたデータ構造を使用して、SwiftオブジェクトとC++オブジェクトの間の接続を維持すると、この危険を回避し、1対1以外の関係を容易にサポートできます。

まず第一に、ここでスウィフトコードの変更をトリガーするC++クラスがある:ここ

typedef void (*cb_t)(const char *, void *); 

class MyClassCPP { 
public: 
    MyClassCPP(cb_t callBack, void * p) : myCallBack(callBack), clientPtr(p) {} 
    void doWork(); // perform some work and invoke the callback 
private: 
    cb_t myCallBack; 
    void * clientPtr; 
}; 
void MyClassCPP::doWork() { 
    myCallBack("C++ code at work...", clientPtr); 
} 

直接、架橋ヘッダ介しスウィフトコードに可視化されるべき目的-C++ラッパーインタフェースであるか、または間接的にC++の型は参照していないことに注意してください。

@class SwiftClass; // forward declaration 
        // can't include *-Swift.h in a header 

@interface OCWrapper : NSObject 

-(instancetype)init:(SwiftClass *)sc; 
-(void)requestWorkFromCPP; 

@end 

ここにラッパーの実装があります。これはC++型を参照します。 Swiftグローバル関数をC++コードのコールバックとして提供することはできませんが、この目的のためにObjective-C++グローバル関数を提供することができます。

// Extension that deals with C++ specifics that can't be visible to Swift 
@interface OCWrapper() 
{ 
    MyClassCPP * myClassCPP; 
} 
@end 

void callBack(const char * msg, void * swiftClient) 
{ 
    // Danger: what if swiftClient does not point to a SwiftClass instance? 
    [(__bridge SwiftClass*)swiftClient sayHello: 
     [[NSString alloc] initWithBytes: msg length:strlen(msg) 
     encoding:NSASCIIStringEncoding]]; 
} 

@implementation OCWrapper 

-(instancetype)init:(SwiftClass *)sc 
{ 
    myClassCPP = new MyClassCPP(callBack, (__bridge void*)sc); 
    return self; 
} 

-(void)requestWorkFromCPP{ 
    myClassCPP->doWork(); 
} 

@end 

上記はObjective-C++ファイルにある必要があります。 Objective-Cファイルを作成し、ファイル名を.mmに変更します。 Objective-C++がSwift型を使用できるように、* -Swift.hヘッダーも含める必要があります。

は最後に、ここでのObjective-C++ラッパーを経由してC++のコードを使用して、いくつかのスウィフトコードは次のとおりです。

// This is like your Swift view controller 
class SwiftClass : NSObject 
{ 
    var label = "[Empty]" 

    var name : String; 
    init(name : String) { 
     self.name = name 
    } 

    func sayHello(greeting : String) { 
     label = "SwiftClass named " + name + " received greeting: " + greeting 
    } 
} 
... 
     let sc = SwiftClass(name : "Zero") 
     let ocWrapper = OCWrapper(sc) 
     let sc1 = SwiftClass(name : "One") 
     let ocWrapper1 = OCWrapper(sc1) 

     ocWrapper1.requestWorkFromCPP() 
     print("The label value from C++: \(sc1.label)") 

     ocWrapper.requestWorkFromCPP() 
     print("The label value from C++: \(sc.label)") 
... 
関連する問題