128 votes

Utiliser C++ avec Cocoa au lieu d'Objective-C ?

J'aimerais écrire des applications qui utilisent C++ et les frameworks Cocoa parce qu'Apple ne rend pas Carbon compatible avec les 64 bits. L'implémentation de C++ semble assez simple sous Linux et Windows, mais sous Mac OS X, il semble que des éléments de code supplémentaires spécifiques à Apple soient nécessaires (comme un wrapper Obj-C). Il semble également qu'Apple oblige les développeurs à écrire en Objective-C plutôt qu'en C++, mais je peux me tromper.

J'essaie de trouver un moyen d'écrire du code sur le Mac qui serait facile à conserver sur plusieurs plateformes. Il serait très inefficace de devoir écrire du code en C++ pour Linux/Windows, puis d'en réécrire de larges portions en Objective-C.

Existe-t-il un moyen d'écrire du code en C++ qui sera supporté à l'avenir et pris en charge par Xcode ? De même, si cela est possible, comment puis-je mélanger C++ et Objective-C dans Xcode ? Merci.

114voto

Barry Wark Points 73462

Vous ne pouvez pas écrire une application Cocoa entièrement en C++. Cocoa s'appuie fortement sur les capacités de liaison tardive d'Objective-C pour nombre de ses technologies de base, telles que les liaisons clé-valeur, les délégués (style Cocoa) et le modèle cible-action. Les exigences en matière de liaison tardive font que très difficile d'implémenter l'API Cocoa dans un langage typé lié à la compilation comme le C++. Vous pouvez, bien sûr, écrire une application C++ pure qui fonctionne sous OS X. Elle ne peut simplement pas utiliser les API Cocoa.

Vous avez donc deux options si vous souhaitez partager du code entre des applications C++ sur d'autres plateformes et votre application basée sur Cocoa. La première consiste à écrire la couche modèle en C++ et l'interface graphique en Cocoa. Il s'agit d'une approche courante utilisée par certaines applications de très grande taille, dont les suivantes Mathematica . Votre code C++ peut rester inchangé (vous n'avez pas besoin des extensions "funky" d'Apple pour écrire ou compiler du C++ sous OS X). Votre couche contrôleur fera probablement appel à Objective-C++ (peut-être l'extension Apple "funky" à laquelle vous faites référence). Objective-C++ est un sur-ensemble de C++, tout comme Objective-C est un sur-ensemble de C. En Objective-C++, vous pouvez faire des appels au passage de messages de type objc (comme [some-objc-object callMethod]; ) à l'intérieur d'une fonction C++. Inversement, vous pouvez appeler des fonctions C++ à partir du code ObjC, par exemple :

@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

Vous trouverez plus d'informations sur l'Objective-C++ dans la section consacrée au langage Objective-C. guide . La couche de visualisation peut alors être en Objective-C pur.

La deuxième option consiste à utiliser une boîte à outils C++ multiplateforme. Le site Qt pourrait faire l'affaire. Les boîtes à outils multiplateformes sont généralement méprisées par les utilisateurs de Mac parce qu'elles n'offrent pas une apparence et une convivialité parfaites et que les utilisateurs de Mac s'attendent à ce que l'interface utilisateur des applications Mac soit polie. Cependant, Qt fait un travail étonnamment bon, et selon le public et l'utilisation de votre application, cela peut être suffisant. De plus, vous perdrez certaines technologies spécifiques à OS X telles que Core Animation et certaines fonctionnalités de QuickTime, bien qu'il existe des remplacements approximatifs dans l'API Qt. Comme vous le soulignez, Carbon ne sera pas porté en 64 bits. Comme Qt est implémenté sur les API de Carbon, Trolltech/Nokia ont dû porter Qt sur l'API Cocoa pour le rendre compatible avec le 64 bits. D'après ce que j'ai compris, la prochaine version de Qt (actuellement en cours d'élaboration) sera compatible 64 bits. candidat à la libération ) achève cette transition et est compatible 64 bits sous OS X. Vous pouvez jeter un coup d'œil aux sources de Qt 4.5 si vous êtes intéressé par l'intégration de C++ et des API Cocoa.


Pendant un certain temps, Apple a mis l'API Cocoa à la disposition de Java, mais le pont nécessitait un réglage manuel important et était incapable de gérer les technologies plus avancées telles que les liaisons clé-valeur décrites ci-dessus. Actuellement, les langages typés dynamiquement et liés à l'exécution comme Python, Ruby, etc. sont la seule véritable option pour écrire une application Cocoa sans Objective-C (bien que ces passerelles utilisent évidemment Objective-C sous le capot).

0 votes

Je suis actuellement en train d'essayer de porter ma petite application Ogre3D, cela semble TRÈS pénible. Est-ce qu'apple essaie de convertir tout le monde à Objc, ou est-ce que c'est vraiment une fonctionnalité ?

69voto

FX. J. Adi Lima Points 91

Eh bien, cela peut sembler idiot, mais en fait, nous pouvons écrire du code C++ pur pour créer une interface graphique pour Mac OS X, mais nous devons nous lier au cadre 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;
}

17 votes

C'est merveilleux. Existe-t-il des exemples plus compliqués ? Par exemple, l'ouverture d'une fenêtre NSW ?

0 votes

Test1.cpp : Dans la fonction 'int main(int, char**)' : test1.cpp:26:48 : error : cannot convert 'Class {aka objc_class*}' to 'id {aka objc_object*}' in initialization id pool = objc_getClass("NSAutoreleasePool") ; ^ test1. cpp:41:61 : error : cannot convert 'Class {aka objc_class*}' to 'id {aka objc_object*}' for argument '1' to 'objc_object* objc_msgSend(id, SEL, ...)' sel_registerName("sharedApplication")) ; ^

6 votes

@Jichao voir la compatibilité de Clang avec types internes à l'Objective-C - la solution est simple : remplacer objc_getClass con (id)objc_getClass

18voto

fhe Points 3969

Oui, vous pouvez utiliser C++ (c'est-à-dire l'écrire dans des fichiers *.cpp) et même mélanger C++ et Objective-C dans des fichiers *.mm (le code Objective-C standard est stocké dans des fichiers *.m).

Bien sûr, vous devez toujours utiliser Objective-C pour votre interface utilisateur et créer des wrappers Objective-C pour vos objets C++. Une autre option consiste à passer à Qt qui est un framework C++ prenant en charge Windows, Mac OS X et Linux - et sera publié sous la LGPL avec la prochaine version 4.5.

23 votes

Notez que si vous utilisez Qt, votre application sera nulle. Les applications basées sur Qt ne ressemblent pas aux applications Mac natives. (Pour un exemple, voir Google Earth).

1 votes

Oui, c'est probablement un compromis que vous devrez faire. C'est le prix à payer pour la réduction de l'effort de développement :-)

0 votes

Je pense que le gars est intéressé par le développement de jeux.

9voto

Andy Dent Points 9852

Oui, vous pouvez les mélanger.

Vous devez utiliser Objective-C pour opérer directement sur vos objets GUI et recevoir des notifications de leur part.

Ces objets Objective-C peuvent directement faire appel à la logique C++ si vous les placez dans des fichiers .mm, au lieu des fichiers .m purement Objective-C. Notez que vous verrez peut-être des conseils (beaucoup) plus anciens suggérant d'utiliser un .M majuscule pour indiquer Objective-C++, mais cela est très bancal et risque de vous perturber, ainsi que le compilateur.

Vous n'avez pas besoin d'envelopper chaque objet C++, mais votre code Objective-C devra contenir des pointeurs vers ces objets.

Apple ne publie plus d'échantillons montrant comment procéder.

Il existe une excellente vidéo réalisée par Peter Steinberger sur le site Realm. [Objectif] C++ : Qu'est-ce qui pourrait mal tourner ? Je le recommande vivement à tous ceux qui utilisent encore Objective-C++ et vous pouvez rapidement parcourir la transcription.

0 votes

@SteveS votre lien est aussi cassé

0 votes

@fferi - Le lien Steinberger ci-dessus est corrigé. L'intégration Cocoa de Carbon datait de 2007 depuis developer.apple.com, Apple l'a supprimée. Cela indique que vous ne devriez VRAIMENT pas écrire de nouveau code en utilisant les API de Carbon. À ce stade, même la maintenance du code existant utilisant Carbon est risquée. Consultez la réponse acceptée pour cette question, ou celui-ci si vous avez besoin de mélanger C++/Objective C, mais vous ne devriez pas utiliser Carbon. Cela dit, voici : Carbone-Cacao-Intégration

4voto

Matt Stevens Points 6554

Si vous cherchez simplement à utiliser du C++ pur et dur, il est tout à fait possible de le faire et il n'est pas différent des autres plates-formes. Xcode a même un modèle pour cela sous Fichier > Nouveau projet > Utilitaire de ligne de commande > Outil C++. En outre, un certain nombre de bibliothèques open-source populaires (libcurl, libxml2, sqlite, etc.) sont fournies avec OS X et sont disponibles pour la liaison dynamique. Vous n'êtes pas obligé d'utiliser Cocoa ou quoi que ce soit de spécifique à Apple si vous ne le souhaitez pas.

Si vous souhaitez utiliser Cocoa dans certaines parties de votre application, jetez un coup d'oeil à Objectif-C++ . Vous pouvez mélanger C++ et Objective-C dans le même fichier en lui donnant une extension .mm, ou en faisant un clic droit sur le fichier dans Xcode et en sélectionnant Get Info > General puis en changeant le File Type en sourcecode.cpp.objcpp. La deuxième option est utile si vous avez un fichier .cpp dans lequel vous voulez utiliser Objective-C dans un #ifdef spécifique à Mac.

1 votes

Par ailleurs, le modèle C++ (très utile) a disparu avec les versions récentes de Xcode (4.x et 5.x).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X