¿Usar C ++ con Cocoa en lugar de Objective-C?

122

Me gustaría escribir aplicaciones que usen C ++ y los marcos Cocoa porque Apple no está haciendo que Carbon sea compatible con 64 bits. C ++ parece ser bastante vainilla en su implementación en Linux y Windows, pero en Mac OS X parece que se requieren piezas de código específicas de Apple adicionales (como un contenedor Obj-C). También parece que Apple está obligando a los desarrolladores a escribir en Objective-C en lugar de C ++, aunque podría estar equivocado.

Estoy tratando de encontrar una ruta para escribir código en la Mac que sea fácil de mantener multiplataforma. Tener que escribir código en C ++ para Linux / Windows y luego reescribir grandes porciones en Objective-C sería muy ineficiente.

¿Hay alguna manera de escribir código en C ++ que sea compatible en el futuro y en Xcode? Además, si esto es posible, ¿cómo combinaría C ++ y Objective-C en Xcode? Gracias.

Brock Woolf
fuente

Respuestas:

110

No puede escribir una aplicación Cocoa por completo en C ++. El cacao depende en gran medida de las capacidades de enlace tardío de Objective-C para muchas de sus tecnologías principales, como los enlaces de valor clave, los delegados (estilo Cocoa) y el patrón de acción objetivo. Los requisitos de enlace tardío hacen que sea muy difícil implementar la API de Cocoa en un lenguaje tipado de tiempo de compilación como C ++ ⁱ. Por supuesto, puede escribir una aplicación C ++ pura que se ejecute en OS X. Simplemente no puede usar las API de Cocoa.

Por lo tanto, tiene dos opciones si desea compartir código entre aplicaciones C ++ en otras plataformas y su aplicación basada en Cocoa. El primero es escribir la capa del modelo en C ++ y la GUI en Cocoa. Este es un enfoque común utilizado por algunas aplicaciones muy grandes, incluida Mathematica . Su código C ++ puede dejarse sin cambios (no necesita extensiones de manzana "funky" para escribir o compilar C ++ en OS X). Es probable que su capa de controlador haga uso de Objective-C ++ (tal vez la extensión "funky" de Apple a la que se refiere). Objective-C ++ es un superconjunto de C ++, al igual que Objective-C es un superconjunto de C. En Objective-C ++, puede hacer que los mensajes de estilo objc pasen llamadas (como [some-objc-object callMethod];) desde una función de C ++. Por el contrario, puede llamar a funciones C ++ desde el código ObjC como:

@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

Puede encontrar más información sobre Objective-C ++ en la guía del lenguaje Objective-C . La capa de vista puede ser pura Objective-C.

La segunda opción es utilizar un kit de herramientas C ++ multiplataforma. El qtEl juego de herramientas podría ajustarse a la factura. Los kits de herramientas multiplataforma generalmente son despreciados por los usuarios de Mac porque no obtienen todos los detalles de aspecto y sensación exactamente correctos y los usuarios de Mac esperan pulir en la interfaz de usuario de las aplicaciones de Mac. Qt hace un trabajo sorprendentemente bueno, sin embargo, y dependiendo de la audiencia y el uso de su aplicación, puede ser lo suficientemente bueno. Además, perderá algunas de las tecnologías específicas de OS X, como Core Animation y algunas funciones de QuickTime, aunque hay reemplazos aproximados en la API Qt. Como señala, el carbono no se portará a 64 bits. Dado que Qt se implementa en las API de carbono, Trolltech / Nokia ha tenido que portar Qt a la API de Cocoa para que sea compatible con 64 bits. Tengo entendido que la próxima versión de Qt (actualmente en versión candiate) completa esta transición y es compatible con 64 bits en OS X. Si lo desea, puede consultar la fuente de Qt 4.5 si está interesado en integrar C ++ y las API de Cocoa.


ⁱ Durante un tiempo, Apple puso la API de Cocoa a disposición de Java, pero el puente requirió un ajuste manual extenso y no pudo manejar las tecnologías más avanzadas, como los enlaces de valor clave descritos anteriormente. Actualmente, los lenguajes de tiempo de ejecución de tipo dinámico, como Python, Ruby, etc., son la única opción real para escribir una aplicación Cocoa sin Objective-C (aunque, por supuesto, estos puentes usan Objective-C bajo el capó).

Barry Wark
fuente
Actualmente estoy tratando de portar mi pequeña aplicación Ogre3D, parece MUY doloroso. ¿Está Apple tratando de convertir a todos a Objc, o es realmente una característica?
jokoon
68

Bueno, puede sonar tonto, pero en realidad podemos escribir código C ++ puro para crear GUI para Mac OS X, pero debemos vincularnos con el marco 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
fuente
16
Esto es maravilloso. ¿Hay ejemplos más complicados disponibles? Por ejemplo, ¿abrir una NSWindow?
imallett 01 de
test1.cpp: en la función 'int main (int, char **)': test1.cpp: 26: 48: error: no se puede convertir 'Class {aka objc_class *}' a 'id {aka objc_object *}' en la identificación de inicialización pool = objc_getClass ("NSAutoreleasePool"); ^ test1.cpp: 41: 61: error: no se puede convertir 'Class {aka objc_class *}' a 'id {aka objc_object *}' para el argumento '1' a 'objc_object * objc_msgSend (id, SEL, ...)' sel_registerName ("sharedApplication")); ^
Jichao
66
@Jichao ve la compatibilidad de Clang con los tipos internos de Objective-C : la solución es simple: reemplazar objc_getClasscon(id)objc_getClass
Dmitry Isaev
¿Cómo puedo usar un std :: string para configurar, por ejemplo? ¿El título del panel de alerta? Intenté usar c_str () y por igual, pero nada funcionaba ...
MDRE
1
Esto ya no se compila en macOS Catalina
JC Rocamonde
18

Sí, puede usar C ++ (es decir, escribirlo en archivos * .cpp) e incluso mezclar C ++ y Objective-C dentro de archivos * .mm (el código estándar de Objective-C se almacena en archivos * .m).

Por supuesto, todavía tiene que usar Objective-C para su interfaz de usuario y crear envoltorios de Objective-C para sus objetos C ++. Otra opción es cambiar a Qt, que es un Framework C ++ que admite Windows, Mac OS X y Linux, y se lanzará bajo LGPL con la próxima versión 4.5.

fhe
fuente
22
Tenga en cuenta que si usa Qt, su aplicación apestará. Las aplicaciones basadas en Qt no se ven ni se sienten como aplicaciones nativas de Mac. (Para un ejemplo, vea Google Earth.)
Peter Hosey
15
Peter: Eso no es cierto en absoluto. Las aplicaciones basadas en Qt pueden verse y sentirse idénticas a las aplicaciones nativas de Mac, solo necesita hacer ajustes por plataforma, algo que es mucho más fácil que escribir una GUI nativa en cada plataforma.
Mike McQuaid el
11
Mike, estás mal informado. Entre sus otras deficiencias, las aplicaciones basadas en Qt en la Mac no usan los controles nativos en absoluto, y la biblioteca Qt hace todo el dibujo en sí. Esto significa que las aplicaciones Qt no obtienen ninguna aceleración de hardware para el renderizado 2D, no permanecen sincronizadas con los cambios en la interfaz de usuario que Apple hace a los controles estándar, y una aplicación Qt no puede cumplir con el cumplimiento o la capacidad de escritura de ADA a menos que reinvente esos ruedas a ti mismo. En otras palabras, NO INTENTE enviar una aplicación Qt en la Mac. Google puede salirse con la suya: usted no puede.
NSResponder
13
Sí usan los controles nativos, por eso Qt tiene una versión de Cocoa y Carbono. Tiene otros problemas, pero muchas personas envían aplicaciones Qt en Mac y funcionan bien (y perfectamente con un poco de ajustes).
Mike McQuaid
2
El solo uso del control nativo no significa que se verá y se sentirá como aplicaciones nativas. Lo que hace una sensación nativa es la diferencia de cada sistema operativo. Si ajusta su aplicación para que se sienta en una plataforma específica, no se sentirá nativa en otra plataforma. Y, el ajuste fino de comportamientos pequeños en una capa abstraída siempre es más difícil que hacerlo en la capa nativa.
eonil
9

Sí, puedes mezclarlos.

Debe usar Objective-C para operar directamente en sus objetos GUI y recibir notificaciones de ellos.

Estos objetos Objective-C pueden llamar directamente a la lógica de C ++ si los coloca en archivos .mm, en lugar de los archivos Objective-C .m puros. Tenga en cuenta que puede ver consejos (mucho) más antiguos que sugieren el uso de una .M mayúscula para indicar Objective-C ++, pero esto es muy escamoso y es probable que lo confunda a usted y al compilador.

No necesita ajustar todos y cada uno de los objetos de C ++, pero su código Objective-C deberá contener punteros a ellos.

Apple ya no publica ninguna muestra que muestre cómo hacer esto.

Hay un gran video de Peter Steinberger alojado en el Reino [Objetivo] C ++: ¿Qué podría salir mal? Recomiendo encarecidamente a cualquier persona que todavía use Objective-C ++ y pueda leer rápidamente la transcripción.

Andy Dent
fuente
@SteveS tu enlace también está roto
fferri
@fferi - El enlace de Steinberger arriba está arreglado. Carbon Cocoa Integration fue de 2007 de developer.apple.com, Apple lo eliminó. Esto indica que REALMENTE no deberías escribir código nuevo usando las API de Carbon. En este punto, incluso mantener el código existente usando Carbon es arriesgado. Consulte la respuesta aceptada para esta pregunta, o esta si necesita mezclar C ++ / Objective C, pero no debe usar Carbon. Dicho esto, aquí: Integración de carbono-cacao
SteveS
4

Si solo está buscando usar C ++ simple, esto es absolutamente compatible y realmente no es diferente de cualquier otra plataforma. Xcode incluso tiene una plantilla para ello en Archivo> Nuevo proyecto> Utilidad de línea de comandos> Herramienta C ++. Además, varias de las bibliotecas populares de código abierto (libcurl, libxml2, sqlite, etc.) vienen con OS X y están disponibles para la vinculación dinámica. No tiene que usar Cocoa ni nada específico de Apple si no lo desea.

Si desea utilizar Cocoa en ciertas partes de su aplicación, eche un vistazo a Objective-C ++ . Puede mezclar C ++ y Objective-C en el mismo archivo dándole una extensión de .mm, o haciendo clic derecho en el archivo en Xcode y seleccionando Obtener información> General y luego cambiando el Tipo de archivo a sourcecode.cpp.objcpp. La segunda opción es útil si tiene un archivo .cpp donde desea usar Objective-C dentro de un #ifdef específico de Mac.

Matt Stevens
fuente
1
Por cierto, la plantilla C ++ (realmente útil) desapareció con versiones recientes de Xcode (4.xy 5.x)
Jay
1

Aunque esta es una pregunta de años ...

He intentado hacer un envoltorio de C ++ de algunas clases de cacao .

Fue una experiencia muy bonita. C ++ proporcionó una mejor seguridad de tipografía que Objective-C, y me hizo escribir menos código. Pero el tiempo de compilación y la seguridad de la memoria son peores. Es posible, pero algunas características basadas en dinámicas no fueron fáciles de manejar. Creo que no tiene sentido tratarlo en C ++.

De todos modos, mi proyecto fue finalmente abandonado debido al anuncio de Swift. Al principio, borró todas las razones por las que quería usar C ++, y proporciona aún más y mejor.

eonil
fuente
0

Si está escribiendo una aplicación puramente gráfica, es decir, está dibujando todo usando código, considere openFrameworks . Es un lenguaje de programación gráfico de código abierto creado sobre C / C ++. Tiene complementos que permiten a las personas ampliar el idioma. Tienen un complemento para el iphone . Creo que viene con la biblioteca y los proyectos XCode que te ayudarán a compilar aplicaciones para iPhone y iPod touch.

Milesmeow
fuente