¿Puedo mezclar Swift con C++? Como los archivos Objective-C.mm
(12)
Cambié mis archivos .m a .mm y uso C ++. ¿Hay alguna manera de hacer lo mismo con Swift?
Acabo de hacer un pequeño proyecto de ejemplo usando Swift, Objective-C y C ++. Es una demostración de cómo usar las costuras OpenCV en iOS. La API de OpenCV es C ++, por lo que no podemos hablar directamente desde Swift. Uso una clase contenedora 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 clang para automatizar la comunicación C ++ / swift. Puede instanciar clases de C ++ de rápido, heredar de la clase de C ++ e incluso anular los métodos virtuales de forma rápida.
Analizará la clase C ++ que desea exportar rápidamente y generará automáticamente el puente Objective-C / Objective-C ++.
En caso de que esto sea útil para cualquier persona, también tengo un breve tutorial sobre cómo llamar a una simple biblioteca estática de C ++ desde una utilidad de línea de comandos de Swift trivial. Esta es una pieza de código de prueba de concepto realmente escueta.
Sin Objective-C involucrado, solo Swift y C ++. El código en una biblioteca C ++ es llamado por un contenedor C ++ que implementa una función con un enlace externo "C". A continuación, se hace referencia a esa función en el encabezado de puente y se llama desde Swift.
Escribí un proyecto simple de Xcode 6 que muestra cómo mezclar C ++, Objective C y el 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 de C ++ del Swift.
La clave es crear un encabezado compartido Project-Bridging-Header.h y colocar allí los encabezados Objective C.
Descargue el proyecto como un ejemplo completo.
La confusión puede provenir 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 ese tipo. No es el .mm
que causa la fricción con .cpp
, es el encabezado .h
que positivamente no debe ser un encabezado C++
.
Mismo proyecto: sí.
En el mismo proyecto, puede felizmente mezclar 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 automáticamente sus clases Swift marcadas con@objc
a Objective-C -
.h
: esta es la parte difícil, ya que se usan ambiguamente para todos los sabores de C , ++ o no, objetivo o no. Cuando a.h
no contiene una sola palabra clave C ++ , comoclass
, se puede agregar al...Bridging-Header.h
, y expondrá cualquier función que corresponda a las funcionalidades.c
o.cpp
que declara. De lo contrario, ese encabezado debe estar envuelto en una API pura C o Objective-C .
Mismo archivo: No.
En el mismo archivo, no puede mezclar todos 5. En el mismo archivo fuente :
-
.swift
: no se puede mezclar Swift con nada -
.m
: puedes mezclar Objective-C con C. ( @Vinzzz ) -
.mm
: puedes mezclar Objective-C con C ++ . Este puente es Objective-C ++ . ( @Vinzzz ). -
.c
: C puro -
.cpp
: puedes mezclar C ++ y Assembly ( @Vality ) -
.h
: C , C ++ , Objective-C u Objective-C ++ omnipresente y ambiguo, por lo que la respuesta es que depende.
Referencias
- Asamblea de invocación de C ++ ( Brett Hale )
- Invoque Swift desde Objective-C ( Svitlana )
- Invoque C, C ++, Obj-C, Obj-C ++ de Swift ( SwiftArchitect , uno mismo)
- Para descargar un proyecto completo de iOS 9, Xcode 7, busque SO-32541268 en Swift Recipes.
No, no en un solo archivo.
Sin embargo, puede usar C ++ en proyectos Swift sin necesidad de una biblioteca o marco estático. Como han dicho otros, la clave es crear un encabezado puente de 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 que cabría esperar.
Este archivo (c.swift) compila a un ejecutable válido con swiftc c.swift
y clang -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;
}
// */
Proporciono un enlace a SE-0038 en el recurso oficial, que se describe como Esto mantiene propuestas de cambios y mejoras visibles para el usuario en el Lenguaje de programación Swift.
El estado actual es que esta es la solicitud de función que se aceptó pero aún no se programó.
Este enlace está destinado a dirigir a cualquiera que busque esta característica en la dirección correcta
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 puede omitir el archivo Objective-C en el medio. Simplemente agregue un archivo de encabezado C con un archivo fuente .cpp. Tener solo declaraciones C en el archivo de cabecera e incluir 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;
}
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 demo http://flopalm.com/opencv-with-swift/ .
No. Cuando cambia de .m a .mm, en realidad está cambiando de Objective-C a un idioma 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 todas las C como entrada). Cuando digo que no es bastante C ++, considere un archivo C ++ que incluya una variable llamada nil
(que es legal C ++) y luego intente compilar eso 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 archivo .swift
.
"Usar Swift con Cocoa 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 ++.