Gunakan C ++ dengan Cocoa, bukan Objective-C?

122

Saya ingin menulis aplikasi yang menggunakan C ++ dan kerangka kerja Cocoa karena Apple tidak membuat Carbon 64-bit mampu. C ++ tampaknya cukup vanilla dalam implementasinya di Linux dan Windows tetapi di Mac OS X sepertinya diperlukan potongan kode khusus Apple tambahan (seperti pembungkus Obj-C). Sepertinya Apple juga memaksa pengembang untuk menulis di Objective-C daripada C ++, meskipun saya bisa salah.

Saya mencoba menemukan jalur untuk menulis kode di Mac yang akan mudah untuk tetap lintas platform. Harus menulis kode dalam C ++ untuk Linux / Windows dan kemudian menulis ulang sebagian besar di Objective-C akan sangat tidak efisien.

Apakah ada cara untuk menulis kode dalam C ++ yang akan didukung di masa mendatang dan didukung di Xcode? Juga, jika ini memungkinkan, bagaimana cara mencampur C ++ dan Objective-C di Xcode? Terima kasih.

Brock Woolf
sumber

Jawaban:

110

Anda tidak dapat menulis aplikasi Kakao seluruhnya dalam C ++. Kakao sangat bergantung pada kemampuan pengikatan akhir dari Objective-C untuk banyak teknologi intinya seperti Pengikatan Nilai-Kunci, delegasi (gaya Kakao), dan pola tindakan target. Persyaratan pengikatan yang terlambat membuatnya sangat sulit untuk mengimplementasikan API Kakao dalam bahasa yang diketik dengan batasan waktu kompilasi seperti C ++ ⁱ. Anda tentu saja dapat menulis aplikasi C ++ murni yang berjalan di OS X. Aplikasi tersebut tidak dapat menggunakan Cocoa API.

Jadi, Anda memiliki dua opsi jika Anda ingin berbagi kode antara aplikasi C ++ di platform lain dan aplikasi berbasis Cocoa Anda. Yang pertama adalah menulis lapisan model di C ++ dan GUI di Cocoa. Ini adalah pendekatan umum yang digunakan oleh beberapa aplikasi yang sangat besar, termasuk Mathematica . Kode C ++ Anda dapat dibiarkan tidak berubah (Anda tidak perlu ekstensi apple "funky" untuk menulis atau mengkompilasi C ++ di OS X). Lapisan pengontrol Anda kemungkinan besar akan menggunakan Objective-C ++ (mungkin ekstensi Apple "funky" yang Anda maksud). Objective-C ++ adalah superset dari C ++, sama seperti Objective-C adalah superset dari C. Dalam Objective-C ++, Anda dapat membuat panggilan pesan gaya objc (seperti [some-objc-object callMethod];) dari dalam fungsi C ++. Sebaliknya, Anda dapat memanggil fungsi C ++ dari dalam kode ObjC seperti:

@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

Anda dapat mengetahui lebih lanjut tentang Objective-C ++ di panduan bahasa Objective-C . Lapisan tampilan kemudian bisa murni Objective-C.

Opsi kedua adalah menggunakan toolkit C ++ lintas platform. The Qttoolkit mungkin sesuai dengan tagihan. Toolkit lintas platform umumnya dibenci oleh pengguna Mac karena mereka tidak mendapatkan semua detail tampilan dan nuansa dengan tepat dan pengguna Mac mengharapkan polesan di UI aplikasi Mac. Namun, Qt melakukan pekerjaan yang sangat bagus, dan bergantung pada audiens dan penggunaan aplikasi Anda, itu mungkin cukup baik. Selain itu, Anda akan kehilangan beberapa teknologi khusus OS X seperti Animasi Inti dan beberapa fungsionalitas QuickTime, meskipun ada perkiraan penggantian dalam API Qt. Seperti yang Anda tunjukkan, Carbon tidak akan ditransfer ke 64-bit. Sejak Qt diimplementasikan pada Carbon API, Trolltech / Nokia harus mem-port Qt ke Cocoa API agar kompatibel dengan 64-bit. Pemahaman saya adalah bahwa relase berikutnya dari Qt (saat ini dalam rilis candiate) menyelesaikan transisi ini dan kompatibel dengan 64-bit di OS X. Anda mungkin ingin melihat sumber Qt 4.5 jika Anda tertarik untuk mengintegrasikan C ++ dan Cocoa API.


ⁱ Untuk sementara waktu Apple membuat Cocoa API tersedia untuk Java, tetapi bridge membutuhkan penyetelan manual yang ekstensif dan tidak dapat menangani teknologi yang lebih maju seperti Key-Value Binding yang dijelaskan di atas. Saat ini diketik secara dinamis, bahasa terikat waktu proses seperti Python, Ruby, dll. Adalah satu-satunya pilihan nyata untuk menulis aplikasi Cocoa tanpa Objective-C (meskipun tentu saja jembatan ini menggunakan Objective-C di bawah tenda).

Barry Wark
sumber
Saat ini saya mencoba mem-porting aplikasi Ogre3D kecil saya, sepertinya SANGAT menyakitkan. Apakah apple mencoba mengonversi semua orang ke Objc, atau apakah ini benar-benar fitur?
jokoon
68

Mungkin terdengar konyol, tetapi sebenarnya kita dapat menulis kode C ++ murni untuk membuat GUI untuk Mac OS X, tetapi kita harus menautkan ke kerangka kerja 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;
}
FX. J. Adi Lima
sumber
17
Ini luar biasa. Apakah ada contoh yang lebih rumit yang tersedia? Misalnya, membuka NSWindow?
imallett
test1.cpp: Dalam fungsi 'int main (int, char **)': test1.cpp: 26: 48: error: tidak dapat mengubah 'Class {aka objc_class *}' menjadi 'id {aka objc_object *}' dalam inisialisasi id pool = objc_getClass ("NSAutoreleasePool"); ^ test1.cpp: 41: 61: error: tidak dapat mengubah 'Class {aka objc_class *}' menjadi 'id {aka objc_object *}' untuk argumen '1' menjadi 'objc_object * objc_msgSend (id, SEL, ...)' sel_registerName ("sharedApplication")); ^
Jichao
6
@Jichao lihat kompatibilitas Clang dengan tipe Objective-C internal - perbaikannya sederhana: ganti objc_getClassdengan(id)objc_getClass
Dmitry Isaev
Bagaimana saya bisa menggunakan std :: string untuk menyetel mis. judul untuk panel peringatan? Saya mencoba menggunakan c_str () dan sejenisnya tetapi tidak ada yang berhasil ...
mdre
1
Ini tidak dapat dikompilasi lagi di macOS Catalina
JC Rocamonde
18

Ya, Anda bisa menggunakan C ++ (yaitu menulisnya dalam file * .cpp) dan bahkan mencampur C ++ dan Objective-C di dalam file * .mm (kode standar Objective-C disimpan dalam file * .m).

Tentu saja, Anda masih harus menggunakan Objective-C untuk antarmuka pengguna Anda dan membuat pembungkus Objective-C untuk objek C ++ Anda. Pilihan lain adalah beralih ke Qt yang merupakan C ++ Framework yang mendukung Windows, Mac OS X, dan Linux - dan akan dirilis di bawah LGPL dengan versi 4.5 berikutnya.

fhe
sumber
23
Perhatikan bahwa jika Anda menggunakan Qt, aplikasi Anda akan payah. Aplikasi berbasis Qt tidak terlihat dan terasa seperti aplikasi Mac asli. (Sebagai contoh, lihat Google Earth.)
Peter Hosey
15
Peter: Itu tidak benar sama sekali. Aplikasi berbasis Qt dapat terlihat dan terasa identik dengan aplikasi Mac asli, Anda hanya perlu melakukan penyesuaian per platform, sesuatu yang jauh lebih mudah daripada menulis GUI asli di setiap platform.
Mike McQuaid
12
Mike, Anda salah informasi. Di antara kekurangan mereka yang lain, aplikasi berbasis Qt di mac tidak menggunakan kontrol asli sama sekali, dan pustaka Qt melakukan semua gambar itu sendiri. Ini berarti bahwa aplikasi Qt tidak mendapatkan akselerasi perangkat keras apa pun untuk rendering 2D, aplikasi tersebut tidak tetap sinkron dengan perubahan UI yang dibuat Apple pada kontrol standar, dan aplikasi Qt tidak dapat memberikan kepatuhan ADA atau skrip kecuali Anda menemukannya kembali. roda sendiri. Dengan kata lain, JANGAN COBA untuk mengirimkan aplikasi Qt di Mac. Google bisa lolos begitu saja: Anda tidak bisa.
NSResponder
13
Mereka memang menggunakan kontrol asli, itulah mengapa Qt memiliki versi Cocoa and Carbon. Ini memiliki masalah lain tetapi banyak orang mengirimkan aplikasi Qt di Mac dan mereka berfungsi dengan baik (dan sempurna dengan sedikit tweaker).
Mike McQuaid
2
Hanya menggunakan kontrol asli tidak berarti itu akan terlihat dan terasa seperti aplikasi asli. Apa yang membuat perasaan asli adalah perbedaan dari setiap OS. Jika Anda menyesuaikan aplikasi agar terasa di platform tertentu, aplikasi tidak akan terasa asli di platform lain. Dan, menyempurnakan perilaku kecil pada lapisan yang pernah diabstraksi selalu lebih sulit daripada melakukannya pada lapisan asli.
eonil
9

Ya, Anda bisa mencampurnya.

Anda perlu menggunakan Objective-C untuk langsung mengoperasikan objek GUI Anda dan menerima pemberitahuan dari mereka.

Objek Objective-C ini bisa langsung memanggil logika C ++ jika Anda meletakkannya dalam file .mm, bukan file Objective-C .m murni. Perhatikan bahwa Anda mungkin melihat (banyak) saran lama yang menyarankan penggunaan huruf besar .M untuk menunjukkan Objective-C ++ tetapi ini sangat tidak pasti dan mungkin akan membingungkan Anda serta kompilernya.

Anda tidak perlu membungkus setiap dan setiap objek C ++ tetapi kode Objective-C Anda harus berisi pointer ke sana.

Apple tidak lagi menerbitkan sampel apa pun yang menunjukkan cara melakukan ini.

Ada video hebat oleh Peter Steinberger yang dihosting di Realm [Objective] C ++: What Could Possibly Go Wrong? Saya sangat merekomendasikan bagi siapa saja yang masih menggunakan Objective-C ++ dan Anda dapat membaca transkripnya dengan cepat.

Andy Dent
sumber
@SteveS tautan Anda juga rusak
fferri
@fferi - Tautan Steinberger di atas telah diperbaiki. Carbon Cocoa Integration berasal dari 2007 dari developer.apple.com, Apple menghapusnya. Ini menunjukkan bahwa Anda BENAR-BENAR tidak boleh menulis kode baru menggunakan API Karbon. Pada titik ini, bahkan mempertahankan kode yang ada dengan menggunakan Karbon berisiko. Lihat jawaban yang diterima untuk pertanyaan ini, atau yang ini jika Anda perlu mencampur C ++ / Objective C, tetapi Anda tidak boleh menggunakan Karbon. Yang mengatakan, di sini: Carbon-Cocoa-Integration
SteveS
4

Jika Anda hanya ingin menggunakan vanilla C ++ polos, ini benar-benar didukung dan tidak berbeda dari platform lain. Xcode bahkan memiliki templat untuk itu di bawah File> Proyek Baru> Utilitas Baris Perintah> Alat C ++. Selain itu, sejumlah pustaka sumber terbuka yang populer (libcurl, libxml2, sqlite, dll) hadir dengan OS X dan tersedia untuk penautan dinamis. Anda tidak harus menggunakan Cocoa atau apa pun khusus Apple jika Anda tidak mau.

Jika Anda ingin menggunakan Cocoa di bagian tertentu dari aplikasi Anda, lihat Objective-C ++ . Anda dapat mencampur C ++ dan Objective-C dalam file yang sama dengan memberinya ekstensi .mm, atau dengan mengklik kanan pada file di Xcode dan memilih Get Info> General kemudian mengubah Jenis File menjadi sourcecode.cpp.objcpp. Opsi kedua berguna jika Anda memiliki file .cpp di mana Anda ingin menggunakan Objective-C dalam #ifdef khusus Mac.

Matt Stevens
sumber
1
BTW, template C ++ (sangat berguna) hilang dengan versi terbaru Xcode (4.x dan 5.x)
Jay
1

Meskipun ini pertanyaan lama ...

Saya telah mencoba membuat bungkus C ++ dari beberapa kelas Cocoa .

Itu pengalaman yang cukup menyenangkan. C ++ memberikan keamanan tipe yang lebih baik daripada Objective-C, dan membuat saya menulis lebih sedikit kode. Tetapi waktu kompilasi dan keamanan memori lebih buruk. Itu mungkin tetapi beberapa fitur berbasis dinamis tidak mudah ditangani. Saya pikir tidak masuk akal untuk menghadapinya di C ++.

Pokoknya proyek saya akhirnya terbengkalai karena pengumuman Swift. Itu menghapus semua alasan saya ingin menggunakan C ++ pada awalnya, dan memberikan lebih banyak dan lebih baik.

eonil
sumber
0

Jika Anda menulis aplikasi grafis murni, misalnya Anda menggambar semuanya menggunakan kode, pertimbangkan openFrameworks . Ini adalah bahasa pemrograman grafis open source yang dibangun di atas C / C ++. Ini memiliki addons yang memungkinkan orang untuk memperluas bahasa. Mereka memiliki addon untuk iphone . Saya percaya itu datang dengan perpustakaan dan proyek XCode yang akan membantu Anda menyusun aplikasi untuk iPhone dan iPod touch.

milesmeow
sumber