Właśnie zmieniłem moje pliki .m na .mm i używam C ++. Czy jest sposób, aby zrobić to samo w Swift?
Odpowiedzi:
Nie. Kiedy przełączasz się z .m na .mm, tak naprawdę przełączasz się z Objective-C na inny język (który ma wiele subtelnych różnic) zwany Objective-C ++. Więc tak naprawdę nie używasz C ++; używasz Objective-C ++, który akceptuje większość C ++ jako dane wejściowe (w taki sam sposób, w jaki C ++ akceptuje większość, ale nie całe C jako dane wejściowe). Kiedy mówię, że nie jest to całkiem C ++, rozważ plik C ++, który zawiera zmienną o nazwie nil
(która jest poprawną wersją C ++), a następnie spróbuj skompilować ją jako Objective-C ++.
Swift nie ma takiego samego związku. Nie jest to nadzbiór języków C ani C ++ i nie można ich bezpośrednio użyć w .swift
pliku.
„Używanie Swift z Cocoa i Objective-C” mówi nam również:
Nie można importować kodu C ++ bezpośrednio do Swift. Zamiast tego utwórz otokę Objective-C lub C dla kodu C ++.
.mm
swoich plików i (prawie) skończyć. Nie tak z Szybkim.
nil
, na przykładint nil
Zamieszanie może wynikać z założenia, że wystarczy zmienić rozszerzenie pliku z .m
na .mm
, aby połączyć języki, podczas gdy w rzeczywistości nic takiego nie robi. To nie jest to, .mm
co powoduje tarcie .cpp
, to .h
nagłówek, który zdecydowanie nie może być C++
nagłówkiem.
W tym samym projekcie możesz szczęśliwie mieszać C , C ++ , Objective-C , Objective C ++ , Swift , a nawet Assembly .
...Bridging-Header.h
: udostępniasz C , Objective-C i Objective-C ++ w Swift za pomocą tego mostu<ProductModuleName>-Swift.h
: Naraża automatycznie swoje Swift klas oznaczonych @objc
do Objective-C.h
: to jest trudna część, ponieważ są one niejednoznacznie używane dla wszystkich smaków C , ++ lub nie, Cel lub nie. Gdy .h
nie zawiera pojedynczy C ++ słów kluczowych, jak class
to może być dodane do ...Bridging-Header.h
i narazi niezależnie funkcjonować odpowiednie .c
lub .cpp
funkcjonalności deklaruje. W przeciwnym razie ten nagłówek musi być opakowany w czysty interfejs API C lub Objective-C .W tym samym pliku nie można mieszać wszystkich 5. W tym samym pliku źródłowym :
.swift
: nie możesz mieszać Swifta z niczym.m
: Można mieszać Objective-C z C . ( @Vinzzz ).mm
: możesz mieszać Objective-C z C ++ . Ten most to Objective-C ++ . ( @Vinzzz )..c
: czysty C.cpp
: możesz mieszać C ++ i Assembly ( @Vality ).h
: wszechobecny i niejednoznaczny C , C ++ , Objective-C lub Objective-C ++ , więc odpowiedź brzmi: to zależy.Bibliografia
Napisałem prosty projekt Xcode 6, który pokazuje, jak łączyć kod C ++, Objective C i Swift:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
W szczególności przykład wywołuje funkcję Objective C i C ++ z języka Swift.
Kluczem jest utworzenie współdzielonego nagłówka Project-Bridging-Header.h i umieszczenie tam nagłówków Objective C.
Pobierz projekt jako kompletny przykład.
ObjCtoCPlusPlus.h
/ `.mm` istnieje wyłącznie w celu zapewnienia interfejsu Ob-C do kodu C ++ - jest to mostek, który jest tutaj niezbędnym komponentem. Pozostaw dołączenia tam, gdzie się znajdują, i dodaj metodę w ObjCtoCPlusPlus.…
plikach dla każdej metody C ++, do której potrzebujesz dostępu. Dobrze by było, gdybyś przeczytał sourcemaking.com/design_patterns/adapter
Możesz także pominąć plik Objective-C pomiędzy. Po prostu dodaj plik nagłówkowy C z plikiem źródłowym .cpp. Miej tylko deklaracje C w pliku nagłówkowym i dołącz dowolny kod C ++ do pliku źródłowego. Następnie dołącz plik nagłówkowy C do ** - Bridging-Header.h.
Poniższy przykład zwraca wskaźnik do obiektu C ++ (struct Foo), dzięki czemu Swift może przechowywać w COpaquePointer zamiast definiowania struktury Foo w przestrzeni globalnej.
Plik Foo.h (widziany przez Swift - zawarty w pliku pomostowym)
#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
Wewnątrz pliku źródłowego Foo.cpp (niewidoczny dla 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"
zawijanie nagłówka w miejscu, w którym jest zawarty, a nie #ifdef
w samym pliku nagłówkowym. Znakomity!
Właśnie wykonałem mały przykładowy projekt przy użyciu Swift, Objective-C i C ++. To demonstracja, jak używać zszywania OpenCV w iOS. OpenCV API to C ++, więc nie możemy rozmawiać z nim bezpośrednio z Swift. Używam małej klasy opakowania, której plik implementacji to Objective-C ++. Plik nagłówkowy jest czysty Objective-C, więc Swift może rozmawiać z tym bezpośrednio. Musisz uważać, aby nie importować pośrednio żadnych plików C ++ - ish do nagłówków, z którymi współdziała Swift.
Projekt jest tutaj: https://github.com/foundry/OpenCVSwiftStitch
Oto moja próba użycia narzędzia Clang do automatyzacji C ++ / szybkiej komunikacji. Możesz tworzyć klasy C ++ ze swift, dziedziczyć z klasy C ++, a nawet przesłonić metody wirtualne w swift.
Spanalizuje klasę C ++, którą chcesz wyeksportować, aby szybko i automatycznie wygenerować mostek Objective-C / Objective-C ++.
Swift nie jest bezpośrednio kompatybilny z C ++. Możesz obejść ten problem, opakowując kod C ++ za pomocą Objective-C i używając otoki Objective C w języku Swift.
Mam też program demonstracyjny do szybkiego łączenia opencv.
Możesz go pobrać z https://github.com/russj/swift_opencv3_demo .
Więcej informacji o wersji demonstracyjnej http://flopalm.com/opencv-with-swift/ .
Nie, nie w jednym pliku.
Możesz jednak używać języka C ++ w projektach Swift bez konieczności posiadania biblioteki statycznej lub struktury. Jak powiedzieli inni, kluczem jest utworzenie nagłówka mostkującego Objective-C, który # zawiera nagłówki C ++ zgodne z C, które są oznaczone jako zgodne z C za pomocą zewnętrznej sztuczki „C” {} .
Samouczek wideo: https://www.youtube.com/watch?v=0x6JbiphNS4
Inne odpowiedzi są nieco niedokładne. W rzeczywistości możesz mieszać zarówno Swift, jak i [Objective-] C [++] w tym samym pliku, chociaż nie do końca tak, jak byś się spodziewał.
Ten plik (c.swift) kompiluje się do prawidłowego pliku wykonywalnego z zarówno swiftc c.swift
iclang -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;
}
// */
Jedna (z wielu) sztuczek jest taka
Nie możesz po prostu wrzucić @interface i @implementation do tego samego pliku .mm, jak to się często robi.
Więc w swoim pliku nagłówkowym mostkowania masz
#import "Linkage.hpp"
Linkage.hpp ma @interface dla Linkage, a Linkage.mm ma @implementation dla .mm
I wtedy
Umieszczasz tylko #include "yourCpp.hpp"
plik Linkage.mm, a nie plik Linkage.hpp.
W wielu internetowych przykładach / samouczkach autor po prostu umieszcza @interface i @implementation w tym samym pliku .mm, jak to się często robi.
To zadziała w bardzo prostych przykładach mostkowania cpp, ale
Problemem jest:
jeśli twój Cpp.hpp ma jakiekolwiek cechy C ++, które z pewnością będą (jak pierwsza linia #include <something>
), to proces się nie powiedzie.
Ale jeśli po prostu nie masz #include "yourCpp.hpp"
w pliku nagłówkowym Linkage (dobrze jest mieć go w pliku .mm, oczywiście będziesz musiał) - działa.
Niestety, jest to tylko jedna wskazówka w całym procesie.
Na wypadek, gdyby było to pomocne dla każdego, mam również krótki samouczek dotyczący wywoływania prostej biblioteki statycznej C ++ z prostego narzędzia wiersza poleceń Swift. To jest prawdziwy dowód koncepcji kodu.
Bez Objective-C, tylko Swift i C ++. Kod w bibliotece C ++ jest wywoływany przez opakowanie C ++, które implementuje funkcję z zewnętrznym połączeniem „C”. Ta funkcja jest następnie przywoływana w nagłówku mostkowania i wywoływana z języka Swift.
Podaję link do SE-0038 w oficjalnym zasobie, opisanym jako To utrzymuje propozycje zmian i widocznych dla użytkownika ulepszeń w Swift Programming Language.
Stan na dzień dzisiejszy jest taki, że jest to propozycja funkcji, która została zaakceptowana, ale nie została jeszcze zaplanowana.
Ten link ma na celu skierowanie każdego, kto szuka tej funkcji, we właściwym kierunku