混ぜて軽く振る:Qt、Carbon、Cocoa

Qtは、ユーザーインターフェイスを開発するための最も一般的なクロスプラットフォームライブラリと見なすことができます。 同様に、Carbon(C ++)とCocoa(Objective-C)はAppleが使用する主要なフレームワークであり、調和のとれた外観と、使用時にシステムとの最適な統合を意味します。 無料のクローンを作成しようとしましたが、MacOSでのみ完全に実装されています。



多くの人がQtとCocoaの接続を求めたと思いますが、インターネット上に明確な情報がなければ、彼らは大きな成功を収めたとは思われません。





エントリー


Qt 4.5までに、TrolltechはCocoa APIの使用を開始しました。これにより、64ビットプラットフォーム用のアプリケーションを構築できます。 Appleが徐々にアプリケーションを32ビットから64ビットに変換していることは注目に値するため、この措置は非常にタイムリーです。

ほとんどの場合、このバージョンで提供される可能性は十分すぎるほどです。

進歩が進んでいるという事実にもかかわらず、ライブラリの新しいバージョンを使用したくない(または使用できない)人々が残っています。 4.5以降では、Cocoaのサポートなしでアセンブリをインストールした人がいます。 この場合、唯一の解決策はCarbonをリンクとして使用することです。



見かけは簡単ですが、そのようなブリッジの組み立ては簡単なことではありません。

QTのドキュメントでは、Objective-Cと組み合わせた使用についてはほとんど言及されていませんが、これらのファイルの拡張子は.mおよび.mmであり、OBJECTIVE_SOURCESディレクティブに関連付けられていますが、それについては後で詳しく説明します。



ブリッジとして、Objective-C ++で記述されたファイルがあります。これにより、C、C ++、Objective-Cを同時に使用できます。 不快な機能は、実装に応じて、クラスがObjective-Cからメッセージを受信するか、QTにスロットを提供できることです。



概略的には、次のようになります。







ソースコード


Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  1. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  2. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  3. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  4. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  5. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  6. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  7. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end



  8. Copy Source | Copy HTML class menuWrapperPrivate ; // Forward declaration @ interface menuWrapperProxy : NSObject { @ private menuWrapperPrivate * wrap; } - ( void ) emitSayHelloRequested; //, Obj-C - ( menuWrapperPrivate *) getQtProxy; // QObject . Qt . @end







クラスはシェルであるため、ほとんど機能を提供しません。 以下は、menuWrapperPrivateの説明です。



Copy Source | Copy HTML



  1. class menuWrapperPrivatepublic QObject
  2. {
  3. Q_OBJECT
  4. 公開
  5. TrayMenu *メニュー。
  6. 信号:
  7. void sayHello();
  8. 公開スロット:
  9. void privateWrapperSlot(){emit sayHello();};
  10. };




ご覧のとおり、特別なこともありません。 クラスの唯一のタスクは、Objective-C ++からQt(C ++)に呼び出しを転送することです。



Copy Source | Copy HTML



  1. @implementation menuWrapperProxy
  2. -(id)init
  3. {
  4. if ((self = [super init])){
  5. wrap = new menuWrapperPrivate (); // C ++初期化
  6. wrap-> menu = [[TrayMenu alloc] init]; // Objective-Cの初期化
  7. [NSApp setDelegate:wrap-> menu];
  8. [wrap-> menu setParent:self];
  9. }
  10. 自己を返す ;
  11. }
  12. //メッセージ送信機
  13. -( void )emitSayHelloRequested
  14. {
  15. wrap-> privateWrapperSlot(); // C ++呼び出し
  16. }
  17. -( menuWrapperPrivate *)getQtProxy
  18. {
  19. 折り返し;
  20. }
  21. @end




この部分の主要な行は、メニューの初期化です。 TrayMenuクラスは完全にObjective-Cで記述されています(これにより、多くのソースを変更せずに接続できることを示したかったのです)。 コンパイラーがファイルのタイプを正しく判別できるように、拡張子を.mmにする必要があります(原則として、ファイルのタイプを判別しますが、イデオロギー的にはより正確に判別します)



Copy Source | Copy HTML



  1. @ interface TrayMenuNSObject {
  2. @ プライベート
  3. NSStatusItem * _statusItem;
  4. menuWrapperProxy * _parent;
  5. }
  6. -( void )setParent:(menuWrapperProxy *)親;
  7. @end




スペースを節約するために、スクリプトの詳細を意図的に省略しています。



Copy Source | Copy HTML



  1. @implementation TrayMenu
  2. //コールバックソース自体。
  3. -( void )onMyRequest:(id)sender {
  4. [_parent emitSayHelloRequested];
  5. }
  6. -( void )actionQuit:(id)sender {
  7. [NSApp終了:送信者];
  8. }
  9. -(NSMenu *)createMenu {
  10. NSZone * menuZone = [NSMenu menuZone];
  11. NSMenu * menu = [[NSMenu allocWithZone:menuZone] init];
  12. NSMenuItem * menuItem;
  13. menuItem = [menu addItemWithTitle: @ "Say hello"
  14. アクション:@selector(onMyRequest :)
  15. keyEquivalent: @ "" ];
  16. [menuItem setTarget:self];
  17. [メニューaddItem:[NSMenuItem separatorItem]];
  18. menuItem = [menu addItemWithTitle: @ "Quit"
  19. アクション:@selector(actionQuit :)
  20. keyEquivalent: @ "" ];
  21. [menuItem setToolTip: @ "クリックしてこのアプリを終了" ];
  22. [menuItem setTarget:self];
  23. 戻りメニュー。
  24. }
  25. //リソースの読み込みの終了後に呼び出されるオーバーロードされた関数
  26. -( void )applicationDidFinishLaunching:(NSNotification *)通知{
  27. NSMenu * menu = [self createMenu];
  28. _statusItem = [[[NSStatusBar systemStatusBar] //ステータスバーを取得
  29. statusItemWithLength:NSVariableStatusItemLength] retain];
  30. [_statusItem setMenu:menu];
  31. [_statusItem setTitle: @ "Menu" ];
  32. [_statusItem setHighlightMode:YES];
  33. [_statusItem setToolTip: @ "Test Tray" ];
  34. [メニューリリース];
  35. }
  36. -( void )setParent:(menuWrapperProxy *)親
  37. {
  38. _parent = parent;
  39. }
  40. @end


メニューボタンを押すと、シェルおよびプロキシクラスを介してQtアプリケーションに入るイベントが生成されます。 スキームは、より複雑なケースで異なることはほとんどありません。 ファイル拡張子.mに良いトーンを与えます。



Copy Source | Copy HTML



  1. menuWrapperProxy * mwp = [[menuWrapperProxy alloc] init];
  2. menuWrapperPrivate * signalWrapper = [mwp getQtProxy];
  3. QMessageBox * box = new QMessageBox(0);
  4. connect (signalWrapper、SIGNAL(sayHello())、box、SLOT( exec ()));




ちょうどいい? 異なる言語のObj-C ++とクラスが互いに理解し合うことはほとんどありません。







次に、コンパイラにこのすべての恐怖を収集させる必要があります。

ドキュメントでは、.proファイルに指示を追加する必要があります(または、以下を読む)。



OBJECTIVE_SOURCES + = file1.m file2.mm



問題は、最初はqmakeがObective-Cファイルを処理できず、Objective-C ++のみを処理できることです。

スマートな紙片の長期喫煙、タンバリンとのダンス、突っ込む方法は、私が決断を下すのに役立ちました-方向を追加します:



QMAKE_CXXFLAGS = -ObjC ++

QMAKE_CFLAGS = -ObjC ++。



100%真実かどうかはわかりませんが、QMakeディレクティブに関係なく、コードをコンパイルして任意のプロジェクトファイルにObjective-C ++で記述できます。



http://img406.imageshack.us/img406/9150/18285056.jpg



おわりに


この記事があなたのプロジェクトで役立つことを願っています。 インターネット上の他の例とは異なり、コードは機能しており、正直なObjective-Cクラスが含まれており、あいまいなライブラリを必要としません。 ヘッダーファイルを正しく配置するだけで、30分以上かかりません。



PSここは、プロジェクト全体投稿しました。これはコンパイルしやすいでしょう。



All Articles