Respuestas:
No. Cuando cambia de .m a .mm, en realidad está cambiando de Objective-C a un lenguaje diferente (que tiene muchas diferencias sutiles) llamado Objective-C ++. Entonces realmente no estás usando C ++; está utilizando Objective-C ++ que acepta la mayoría de C ++ como entrada (de la misma manera que C ++ acepta la mayoría pero no toda C como entrada). Cuando digo que no es C ++, considere un archivo C ++ que incluya una variable llamada nil
(que es legal C ++) y luego intente compilarlo como Objective-C ++.
Swift no tiene la misma relación. No es un superconjunto de C o C ++, y no se puede usar directamente en un .swift
archivo.
"Usar Swift con cacao y Objective-C" también nos dice:
No puede importar código C ++ directamente en Swift. En su lugar, cree un contenedor Objective-C o C para el código C ++.
.mm
tus archivos y estar (casi) listo. No es así con Swift.
nil
, comoint nil
La confusión puede venir de la suposición de que simplemente cambiar una extensión de archivo de .m
a .mm
es todo lo que necesita para unir los idiomas, cuando, en realidad, no hace nada de eso. No es lo .mm
que causa fricción .cpp
, es el .h
encabezado el que no debe ser un C++
encabezado.
En el mismo proyecto, puede mezclar felizmente C , C ++ , Objective-C , Objective C ++ , Swift e incluso Assembly .
...Bridging-Header.h
: expones C , Objective-C y Objective-C ++ a Swift usando este puente<ProductModuleName>-Swift.h
: Expone de forma automática sus Swift clases marcados con @objc
a Objective-C.h
: esta es la parte difícil, ya que se usan de manera ambigua para todos los sabores de C , ++ o no, objetivo o no. Cuando a .h
no contiene una sola palabra clave de C ++ , como class
, se puede agregar a ...Bridging-Header.h
, y expondrá cualquier función que corresponda .c
o .cpp
funcionalidades que declara. De lo contrario, ese encabezado debe estar envuelto en una API pura de C o Objective-C .En el mismo archivo, no puede mezclar los 5. En el mismo archivo fuente :
.swift
: no puedes mezclar Swift con nada.m
: Usted puede mezclar Objective-C con C . ( @Vinzzz ).mm
: puedes mezclar Objective-C con C ++ . Este puente es Objective-C ++ . ( @Vinzzz )..c
: puro C.cpp
: puedes mezclar C ++ y ensamblaje ( @Vality ).h
: ubicuo y ambiguo C , C ++ , Objective-C u Objective-C ++ , por lo que la respuesta es que depende.Referencias
Escribí un proyecto simple de Xcode 6 que muestra cómo mezclar C ++, Objective C y código Swift:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
En particular, el ejemplo llama a un objetivo C y una función C ++ de Swift.
La clave es crear un encabezado compartido Project-Bridging-Header.h y colocar los encabezados de Objective C allí.
Descargue el proyecto como un ejemplo completo.
ObjCtoCPlusPlus.h
/ `` .mm` existe con el único propósito de proporcionar una interfaz Ob-C al código C ++; es el puente, que es un componente necesario aquí. Deje las inclusiones donde están y agregue un método en los ObjCtoCPlusPlus.…
archivos para cada método C ++ al que necesite acceder. Haría
También puede omitir el archivo Objective-C en el medio. Simplemente agregue un archivo de encabezado C con un archivo fuente .cpp. Tenga solo declaraciones C en el archivo de encabezado e incluya cualquier código C ++ en el archivo fuente. Luego incluya el archivo de encabezado C en ** - Bridging-Header.h.
El siguiente ejemplo devuelve un puntero a un objeto C ++ (struct Foo) para que Swift pueda almacenar en un COpaquePointer en lugar de tener struct Foo definido en el espacio global.
Archivo Foo.h (visto por Swift - incluido en el archivo puente)
#ifndef FOO_H
#define FOO_H
// Strictly C code here.
// 'struct Foo' is opaque (the compiler has no info about it except that
// it's a struct we store addresses (pointers) to it.
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);
#endif
Archivo fuente interno Foo.cpp (no visto por Swift):
extern "C"
{
#include "Foo.h"
}
#include <vector>
using namespace std;
// C++ code is fine here. Can add methods, constructors, destructors, C++ data members, etc.
struct Foo
{
vector<int> data;
};
struct Foo* foo_create()
{
return new Foo;
}
void foo_destroy(struct Foo* foo)
{
delete foo;
}
extern "C"
envolver el encabezado en el lugar donde está incluido en lugar de #ifdef
'editado en el archivo de encabezado. ¡Brillante!
Acabo de hacer un pequeño proyecto de ejemplo usando Swift, Objective-C y C ++. Es una demostración de cómo usar la costura de OpenCV en iOS. La API de OpenCV es C ++, por lo que no podemos hablar con ella directamente desde Swift. Utilizo una clase de contenedor pequeña cuyo archivo de implementación es Objective-C ++. El archivo de encabezado está limpio Objective-C, por lo que Swift puede hablar con esto directamente. Debe tener cuidado de no importar indirectamente ningún archivo C ++ - ish en los encabezados con los que Swift interactúa.
El proyecto está aquí: https://github.com/foundry/OpenCVSwiftStitch
Aquí está mi intento de una herramienta de clang para automatizar la comunicación C ++ / swift. Puede instanciar clases de C ++ de swift, heredar de la clase de C ++ e incluso anular métodos virtuales en swift.
Analizará la clase de C ++ que desea exportar a swift y generará el puente Objective-C / Objective-C ++ automáticamente.
Swift no es directamente compatible con C ++. Puede solucionar el problema envolviendo su código C ++ con Objective-C y utilizando el contenedor Objective C en Swift.
También tengo un programa de demostración para combinar rápidamente OpenCV.
Puede descargarlo desde https://github.com/russj/swift_opencv3_demo .
Más información sobre la demostración http://flopalm.com/opencv-with-swift/ .
No, no en un solo archivo.
Sin embargo, puede usar C ++ en proyectos Swift sin necesidad de una biblioteca o marco estático. Como otros han dicho, la clave es hacer un encabezado de puente Objective-C que # incluya encabezados C ++ compatibles con C que estén marcados como C compatibles con el truco externo "C" {} .
Video tutorial: https://www.youtube.com/watch?v=0x6JbiphNS4
Otras respuestas son ligeramente inexactas. En realidad, puede mezclar Swift y [Objective-] C [++] en el mismo archivo, aunque no del modo esperado.
Este archivo (c.swift) se compila en un ejecutable válido con ambos swiftc c.swift
yclang -x objective-c c.swift
/* /* */
#if 0
// */
import Foundation
print("Hello from Swift!")
/* /* */
#endif
#include <stdio.h>
int main()
{
puts("Hello from C!");
return 0;
}
// */
Un truco (de muchos) es que
No puede simplemente lanzar @interface y @implementation en el mismo archivo .mm como se suele hacer normalmente.
Entonces, en su archivo de encabezado puente tiene
#import "Linkage.hpp"
Linkage.hpp tiene la @interface para Linkage y Linkage.mm tiene la @implementation para .mm
Y entonces
Solo coloca #include "yourCpp.hpp"
el archivo Linkage.mm, no el archivo Linkage.hpp.
En muchos ejemplos / tutoriales en línea, el escritor simplemente coloca la @interface y la @implementation en el mismo archivo .mm, como suele ocurrir.
Eso funcionará en ejemplos de puente cpp muy simples, pero,
El problema es:
si su yourCpp.hpp tiene alguna característica de c ++ que seguramente tendrá (como la primera línea #include <something>
), entonces el proceso fallará.
Pero si simplemente no tiene el archivo de encabezado#include "yourCpp.hpp"
Linkage (está bien tenerlo en el archivo .mm, obviamente necesitará): funciona.
De nuevo, esto es lamentablemente solo un consejo en todo el proceso.
En caso de que esto sea útil para alguien, también tengo un breve tutorial sobre cómo llamar a una biblioteca estática simple de C ++ desde una utilidad trivial de línea de comandos de Swift. Esta es una pieza de código de prueba de concepto realmente básica.
No hay Objective-C involucrado, solo Swift y C ++. El código en una biblioteca de C ++ es llamado por un contenedor de C ++ que implementa una función con enlace externo "C". Luego se hace referencia a esa función en el encabezado de puente y se llama desde Swift.
Estoy proporcionando un enlace a SE-0038 en el recurso oficial, descrito como Esto mantiene propuestas de cambios y mejoras visibles para el usuario al Lenguaje de programación Swift.
El estado actual es que esta es la solicitud de función que se ha aceptado pero aún no está programada.
Este enlace está destinado a dirigir a cualquiera que busque esta función en la dirección correcta