Objective-Cの代わりにCocoaでC ++を使用しますか?


122

AppleはCarbon 64ビット対応ではないため、C ++およびCocoaフレームワークを使用するアプリケーションを記述したいと思います。C ++は、LinuxおよびWindowsでの実装ではかなりバニラのようですが、Mac OS Xでは、追加のApple固有のコード(Obj-Cラッパーなど)が必要なようです。Appleは開発者にC ++ではなくObjective-Cでの記述を強いているようにも見えますが、私は間違っているかもしれません。

私はMacでクロスプラットフォームを維持しやすいコードを書くためのパスを見つけようとしています。Linux / Windows用のC ++でコードを記述してから、Objective-Cで大部分を書き直す必要があると、非常に非効率になります。

将来サポートされ、XcodeでサポートされるコードをC ++で作成する方法はありますか?また、これが可能であれば、C ++とObjective-CをXcodeでどのように混在させることができますか?ありがとう。

回答:


110

Cocoaアプリケーションを完全にC ++で作成することはできません。Cocoaは、キーと値のバインディング、デリゲート(Cocoaスタイル)、ターゲットアクションパターンなどのコアテクノロジの多くについて、Objective-Cのレイトバインディング機能に大きく依存しています。レイトバインディングの要件により、C ++ⁱのようなコンパイル時のバインドされた型付き言語でCocoa APIを実装することが非常に困難になっています。もちろん、OS Xで実行される純粋なC ++アプリを作成することもできます。CocoaAPIを使用することはできません。

したがって、他のプラットフォームのC ++アプリとCocoaベースのアプリケーションの間でコードを共有する場合は、2つのオプションがあります。1つ目は、モデルレイヤーをC ++で作成し、GUIをCocoaで作成することです。これは、Mathematicaを含むいくつかの非常に大きなアプリで使用される一般的なアプローチです。C ++コードを変更せずにそのままにしておくことができます(OS XでC ++を記述またはコンパイルするための「ファンキー」なApple拡張機能は必要ありません)。コントローラー層は、おそらくObjective-C ++を利用するでしょう(おそらく、あなたが参照する「ファンキーな」Apple拡張機能です)。Objective-CがC ++のスーパーセットであるのと同様に、Objective-C ++はC ++のスーパーセットです。Objective- [some-objc-object callMethod];C++では、C ++関数内からobjcスタイルのメッセージ受け渡し呼び出し(など)を実行できます。逆に、次のようなObjCコード内からC ++関数を呼び出すことができます。

@interface MyClass {
    MyCPPClass *cppInstance;
}
@end

@implementation MyClass
- (id)init {
    if(self = [super init]) {
        cppInstance = new MyCPPClass();
    }
    return self;
}
- (void) dealloc {
    if(cppInstance != NULL) delete cppInstance;
    [super dealloc];
}
- (void)callCpp {
    cppInstance->SomeMethod();
}
@end

Objective-C ++の詳細については、Objective-C言語ガイドをご覧ください。ビューレイヤーは、純粋なObjective-Cになります。

2番目のオプションは、クロスプラットフォームのC ++ツールキットを使用することです。Qtのツールキットは法案に合うかもしれません。クロスプラットフォームツールキットは、すべてのルックアンドフィールの詳細が正確に得られず、MacユーザーはMacアプリケーションのUIの洗練を期待しているため、一般にMacユーザーには軽視されています。Qtは驚くほど良い仕事をしますが、オーディエンスとアプリの使用状況によっては、それで十分かもしれません。さらに、Qt APIにはおおよその代替品がありますが、Core Animationや一部のQuickTime機能などの一部のOS X固有のテクノロジーが失われます。ご指摘のとおり、Carbonは64ビットに移植されません。QtはCarbon APIに実装されているため、Trolltech / NokiaはQtをCocoa APIに移植して64ビット互換にする必要がありました。私の理解は、Qtの次のリリース(現在リリース候補中))はこの移行を完了し、OS Xで64ビット互換です。C++とCocoa APIの統合に関心がある場合は、Qt 4.5のソースを確認することをお勧めします。


Appleしばらくの間、AppleはCocoa APIをJavaで使用できるようにしましたが、ブリッジは広範な手動調整を必要とし、上記のキー値バインディングなどのより高度なテクノロジーを処理できませんでした。現在動的に型付けされている、Python、Rubyなどのランタイムバインド言語は、Objective-CなしでCocoaアプリを作成するための唯一の実際のオプションです(もちろん、これらのブリッジは内部でObjective-Cを使用しています)。


私は現在、小さなOgre3Dアプリケーションを移植しようとしていますが、非常に痛いようです。Appleは全員をObjcに変換しようとしているのでしょうか、それとも本当に機能なのでしょうか?
jokoon 2013

68

馬鹿げているように聞こえるかもしれませんが、実際には純粋なC ++コードを記述してMac OS XのGUIを作成できますが、Cocoaフレームワークにリンクする必要があります。

/*
 * test1.cpp
 * This program shows how to access Cocoa GUI from pure C/C++
 * and build a truly functional GUI application (although very simple).
 * 
 * Compile using:
 *   g++ -framework Cocoa -o test1 test1.cpp
 *
 * that will output 'test1' binary.
 */


#include <CoreFoundation/CoreFoundation.h>
#include <objc/objc.h>
#include <objc/objc-runtime.h>
#include <iostream>

extern "C" int NSRunAlertPanel(CFStringRef strTitle, CFStringRef strMsg,
                               CFStringRef strButton1, CFStringRef strButton2, 
                               CFStringRef strButton3, ...);


int main(int argc, char** argv)
{
    id app = NULL;
    id pool = (id)objc_getClass("NSAutoreleasePool");
    if (!pool)
    {
        std::cerr << "Unable to get NSAutoreleasePool!\nAborting\n";
        return -1;
    }
    pool = objc_msgSend(pool, sel_registerName("alloc"));
    if (!pool)
    {
        std::cerr << "Unable to create NSAutoreleasePool...\nAborting...\n";
        return -1;
    }
    pool = objc_msgSend(pool, sel_registerName("init"));

    app = objc_msgSend((id)objc_getClass("NSApplication"),
                       sel_registerName("sharedApplication"));

    NSRunAlertPanel(CFSTR("Testing"),
                    CFSTR("This is a simple test to display NSAlertPanel."),
                    CFSTR("OK"), NULL, NULL);

    objc_msgSend(pool, sel_registerName("release"));
    return 0;
}

16
これは素晴らしい。より複雑な例はありますか?たとえば、NSWindowを開きますか?
イマレット2013

test1.cpp:関数 'int main(int、char **)':test1.cpp:26:48:エラー:初期化IDで 'Class {aka objc_class *}'を 'id {aka objc_object *}'に変換できませんpool = objc_getClass( "NSAutoreleasePool"); ^ test1.cpp:41:61:エラー:引数 '1'から 'objc_object * objc_msgSend(id、SEL、...)'の 'Class {aka objc_class *}'を 'id {aka objc_object *}'に変換できませんsel_registerName( "sharedApplication")); ^
ジチャオ2014年

6
@Jichaoでクランの互換性を参照してください内部のObjective-Cタイプ -修正は簡単です:置き換えるobjc_getClass(id)objc_getClass
ドミトリーIsaev

std :: stringを使用して、例を設定するにはどうすればよいですか。警告パネルのタイトル?私はc_str()などを使ってみましたが、何もうまく
いき

1
これはmacOS Catalinaでコンパイルできなくなりました
JC Rocamonde

18

はい、C ++を使用して(つまり、*。cppファイルに書き込む)、*。mmファイル内でC ++とObjective-Cを混在させることもできます(標準のObjective-Cコードは* .mファイルに格納されます)。

もちろん、ユーザーインターフェイスにObjective-Cを使用し、C ++オブジェクトのObjective-Cラッパーを作成する必要があります。別のオプションは、Qtに切り替えることです。これは、Windows、Mac OS X、およびLinuxをサポートするC ++フレームワークであり、次のバージョン4.5でLGPLの下でリリースされます。


22
Qtを使用している場合、アプリは動作しないことに注意してください。Qtベースのアプリは、ネイティブのMacアプリのようには見えません。(例については、Google Earthを参照してください。)
Peter Hosey、

15
ピーター:それはまったく真実ではありません。Qtベースのアプリは、ネイティブのMacアプリと同じように見えますが、プラットフォームごとに微調整するだけでよく、各プラットフォームでネイティブGUIを作成するよりもはるかに簡単です。
Mike McQuaid

11
マイク、あなたは誤解されています。他の欠点の1つとして、Mac上のQtベースのアプリはネイティブコントロールをまったく使用せず、Qtライブラリ自体がすべての描画を行います。つまり、Qtアプリは2Dレンダリング用のハードウェアアクセラレーションを取得せず、Appleが標準コントロールに対して行ったUIの変更と同期しません。また、Qtアプリは、それらを再発明しない限り、ADAコンプライアンスまたはスクリプト機能を提供できません。あなた自身を動かします。つまり、MacにQtアプリを出荷しようとしないでください。Googleはそれを回避できます。それはできません。
NSResponder

13
彼らはネイティブコントロールを使用します、それがQtがCocoaとCarbonバージョンを持っている理由です。他の問題もありますが、多くの人がQtアプリケーションをMacで出荷しており、正常に動作します(少し調整するだけで完全に動作します)。
Mike McQuaid、2011年

2
ネイティブコントロールを使用するだけでは、ルックアンドフィールになるとは限りませんネイティブアプリケーションのように。ネイティブ感を醸し出すのは各OSの違いです。特定のプラットフォームで感じられるようにアプリを調整しても、別のプラットフォームではネイティブとは感じられません。また、一度抽象化されたレイヤーで小さな動作を微調整することは、ネイティブレイヤーで行うよりも常に困難です。
eonil

9

はい、それらを混ぜることができます。

Objective-Cを使用してGUIオブジェクトを直接操作し、それらから通知を受け取る必要があります。

これらのObjective-Cオブジェクトは、純粋なObjective-C .mファイルではなく.mmファイルに配置すると、C ++ロジックを直接呼び出すことができます。大文字の.Mを使用してObjective-C ++を示すことを示唆する(はるかに)古いアドバイスが表示される場合がありますが、これは非常に不安定で、コンパイラと同様に混乱する可能性があります。

すべてのC ++オブジェクトをラップする必要はありませんが、Objective-Cコードにはそれらへのポインターを含める必要があります。

Appleは、これを行う方法を示すサンプルを公開しなくなりました。

RealmでホストされているPeter Steinbergerによる素晴らしいビデオがあります[目的] C ++:何が問題になるのでしょうか?私はまだObjective-C ++を使用している人には強くお勧めします。


@SteveSあなたのリンクも壊れています
fferri

@fferi-上記のSteinbergerリンクが修正されました。Carbon Cocoa統合は、2007年にdeveloper.apple.comから提供されたもので、Appleはそれを削除しました。これは、Carbon APIを使用して新しいコードを作成するべきではないことを示しています。この時点で、Carbonを使用して既存のコードを維持することさえ危険です。この質問のための受け入れ答え、またはを参照してください、この1 あなたはC ++ / Objective Cのを混在させる必要がある場合がありますが、カーボンを使用するべきではありません。とは言っても、ここで:Carbon-Cocoa-Integration
SteveS '24

4

単純なバニラC ++を使用したいだけの場合、これは完全にサポートされており、他のプラットフォームとまったく同じです。Xcodeには、[ファイル]> [新規プロジェクト]> [コマンドラインユーティリティ]> [C ++ツール]にテンプレートが用意されています。また、人気のあるオープンソースライブラリ(libcurl、libxml2、sqliteなど)の多くはOS Xに付属しており、動的リンクに使用できます。使用したくない場合は、CocoaやApple固有の何かを使用する必要はありません。

アプリの特定の部分でCocoaを使用したい場合は、Objective-C ++をご覧ください。C ++とObjective-Cを同じファイルに混在させるには、拡張子を.mmにするか、Xcodeでファイルを右クリックして[情報を見る]> [一般]を選択し、ファイルタイプをsourcecode.cpp.objcppに変更します。2番目のオプションは、Mac固有の#ifdef内でObjective-Cを使用する.cppファイルがある場合に役立ちます。


1
ところで、(本当に便利な)C ++テンプレートは、Xcodeの最近のバージョン(4.xおよび5.x)でなくなっています
Jay

1

これは何年も前の質問ですが...

私がしているいくつかのCocoaクラスのC ++ラッパーを作ってみました

とてもいい経験でした。C ++はObjective-Cよりも優れた型安全性を提供し、私が書くコードを少なくしました。ただし、コンパイル時間とメモリの安全性は低下します。可能ですが、動的ベースの機能の一部は扱いが簡単ではありませんでした。C ++で処理しても意味がないと思います。

とにかく、私のプロジェクトはSwiftの発表によりようやく中止されました。最初にC ++を使用したい理由をすべてクリアし、さらに多くのことを提供します。


0

純粋にグラフィカルなアプリケーションを作成している場合、つまりコードを使用してすべてを描画している場合は、openFrameworksを検討してください。これは、C / C ++の上に構築されたオープンソースのグラフィカルプログラミング言語です。それは人々が言語を拡張することを可能にするアドオンを持っています。彼らはiphoneのアドオンを持ってます。私は、iPhoneとiPod touch用のアプリをコンパイルするのに役立つライブラリとXCodeプロジェクトが付属していると思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.