Відповіді:
Ні. Коли ви переходите з .m на .mm, ви фактично переходите з Objective-C на іншу мову (яка має багато тонких відмінностей) під назвою Objective-C ++. Таким чином, ви не використовуєте C ++; ви використовуєте Objective-C ++, який приймає більшість C ++ як вхідний (таким же чином, як C ++ приймає більшість, але не всі C як вхідні). Коли я кажу, що це не зовсім C ++, розгляньте файл C ++, який включає змінну з назвоюnil
(яка є законною C ++), а потім спробуйте скомпілювати це як Objective-C ++.
Свіфт не має однакових відносин. Це не набір C або C ++, і ви не можете безпосередньо використовувати жоден .swift
файл.
"Використання Swift з какао та Objective-C" також говорить нам:
Ви не можете імпортувати код C ++ безпосередньо в Swift. Натомість створіть обгортку Objective-C або C для коду C ++.
.mm
своїх файлів і бути (майже) готовим . Не так зі Свіфтом.
nil
, наприкладint nil
Плутанина може виникнути з припущення, що лише зміна розширення файлу з .m
на .mm
це все, що вам потрібно, щоб перевести мови, коли насправді він нічого подібного не робить. Не те, .mm
що викликає тертя з .cpp
, саме .h
заголовок повинен бути позитивно не C++
заголовком.
У цьому ж проекті ви можете із задоволенням змішати C , C ++ , Objective-C , Objective C ++ , Swift і навіть збірку .
...Bridging-Header.h
: Ви піддаєте C , Objective-C і Objective-C ++ для Swift , використовуючи цей міст<ProductModuleName>-Swift.h
: Виставляє автоматично ваші Swift класи , відмічені @objc
в Objective-C.h
: це складна частина, оскільки вони неоднозначно використовуються для всіх ароматів С , ++ чи ні, Об'єктивна чи ні. Якщо a .h
не містить жодного ключового слова C ++ , як-от class
, воно може бути додане до ...Bridging-Header.h
та викриє будь-яку функцію відповідної .c
або .cpp
функціональної функції, яку вона оголошує. В іншому випадку, що заголовок повинен бути обгорнуті або в чистому C або Objective-C API.У тому самому файлі ви не можете змішати всі 5. У цьому ж вихідному файлі :
.swift
: не можна змішувати Свіфт ні з чим.m
: Ви можете змішати Objective-C з C . ( @Vinzzz ).mm
: ви можете змішати Objective-C з C ++ . Цей міст об'єктивний-C ++ . ( @Vinzzz )..c
: чистий С.cpp
: ви можете змішати C ++ та збірку ( @Vality ).h
: всюдисущий і неоднозначний C , C ++ , Objective-C або Objective-C ++ , тому відповідь - це залежить.Список літератури
Я написав простий проект Xcode 6, який показує, як поєднувати код C ++, Objective C і Swift:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
Зокрема, у прикладі називаємо об'єктив C та функцію C ++ від Swift.
Ключовим моментом є створення спільного заголовка Project-Bridging-Header.h та розміщення туди заголовків Objective C.
Завантажте проект як повний приклад.
ObjCtoCPlusPlus.h
/ `` .mm` існує лише з метою надання інтерфейсу Ob-C коду C ++ - це міст, який є необхідним компонентом тут. Залиште включення, де вони є, і додайте метод у ObjCtoCPlusPlus.…
файли для кожного методу C ++, до якого потрібно отримати доступ. Ви б добре , щоб читати над sourcemaking.com/design_patterns/adapter
Ви також можете пропустити Objective-C файл між ними. Просто додайте файл заголовка C із вихідним файлом .cpp. У файлі заголовка є лише декларації C, а будь-який код C ++ у вихідному файлі. Потім додайте файл заголовка C у ** - Bridging-Header.h.
Наступний приклад повертає вказівник на об’єкт C ++ (struct Foo), тому Swift може зберігати в COpaquePointer замість того, щоб у глобальному просторі визначався struct Foo.
Файл Foo.h (бачив Swift - включений до мостового файлу)
#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
Всередині вихідного файлу Foo.cpp (не бачив Свіфт):
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"
загортати заголовок на місце, яке воно включене, а не #ifdef
'ed у самому файлі заголовка. Блискуче!
Я щойно зробив невеликий приклад проекту, використовуючи Swift, Objective-C і C ++. Це демонстрація того, як використовувати зшивання OpenCV в iOS. API OpenCV - це C ++, тому ми не можемо говорити з ним безпосередньо від Swift. Я використовую невеликий клас обгортки, файлом реалізації якого є Objective-C ++. Тема чистий Objective-C, тому Swift може говорити з цим безпосередньо. Ви повинні стежити за тим, щоб не опосередковано імпортувати будь-які файли C ++ в заголовки, з якими взаємодіє Swift.
Проект тут: https://github.com/foundry/OpenCVSwiftStitch
Ось моя спроба кланг-інструменту для автоматизації C ++ / швидкої комунікації. Ви можете інстанціювати класи C ++ з швидкої, успадковувати від класу C ++ і навіть швидко змінювати віртуальні методи.
Він буде розбирати клас C ++, який ви хочете експортувати, для швидкого створення та автоматичного генерування мосту Objective-C / Objective-C ++.
Swift безпосередньо не сумісний із C ++. Ви можете подолати проблему, загорнувши свій код C ++ за допомогою Objective-C та використовуючи обгортку Objective C у Swift.
У мене також є демонстраційна програма для швидкого поєднання opencv.
Ви можете завантажити його з https://github.com/russj/swift_opencv3_demo .
Детальніше про демонстраційну версію http://flopalm.com/opencv-with-swift/ .
Ні, не в одному файлі.
Однак ви можете використовувати C ++ у проектах Swift, не потребуючи статичної бібліотеки чи рамок. Як уже говорили інші, головним є створення мостового заголовка Objective-C, який #include C-сумісні заголовки C ++, які позначені як C, сумісні із зовнішнім трюком "C" {} .
Відеоурок: https://www.youtube.com/watch?v=0x6JbiphNS4
Інші відповіді трохи неточні. Ви можете фактично змішати і Swift, і [Objective-] C [++] в одному файлі, хоча і не зовсім так, як ви очікували.
Цей файл (c.swift) компілюється у дійсний виконуваний файл з обома swiftc c.swift
та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;
}
// */
Один трюк (з багатьох) - це
Ви не можете просто кинути @interface та @implementation в один і той же .mm-файл, як це часто робиться зазвичай.
Отже, у своєму мостовому файлі заголовок у вас є
#import "Linkage.hpp"
Linkage.hpp має @interface для Linkkage, а Linkage.mm має @implementation for .mm
І потім
Ви ставите лише #include "yourCpp.hpp"
у файл Linkage.mm, а не у файл Linkage.hpp.
У багатьох онлайн-прикладах / навчальних посібниках автор просто поміщає @interface та @implementation у той самий файл .mm, як це часто робиться.
Це буде працювати в дуже простих мостових прикладах cpp, але,
Проблема полягає в наступному:
якщо ваш yourCpp.hpp має будь-які функції c ++, які, безумовно, буде (як, наприклад, перший рядок #include <something>
), тоді процес вийде з ладу.
Але якщо ви просто НЕ мають #include "yourCpp.hpp"
в Linkage заголовка файлу (це нормально , щоб мати його в файлі .mm, очевидно , вам потрібно) - це працює.
На жаль, це, на жаль, лише одна порада у всьому процесі.
Якщо це корисно для когось, я також маю короткий підручник із виклику простої статичної бібліотеки C ++ з тривіальної утиліти командного рядка Swift. Це дійсно голий доказ концептуального коду.
Ніякого об'єктивного C не задіяно, просто Swift та C ++. Код у бібліотеці C ++ викликається обгорткою C ++, яка реалізує функцію із зовнішнім зв'язком "C". Потім ця функція посилається в мостовому заголовку і викликається від Swift.
Я надаю посилання на SE-0038 в офіційному ресурсі, описаному як Це підтримує пропозиції щодо змін та видимих для користувача удосконалень мови програмування Swift.
Станом на сьогодні, це запит на функцію, який був прийнятий, але ще не запланований.
Це посилання призначене для того, щоб спрямовувати тих, хто шукає цю функцію, у правильному напрямку