Ответы:
Нет. Когда вы переключаетесь с .m на .mm, вы фактически переключаетесь с Objective-C на другой язык (который имеет много тонких отличий) под названием Objective-C ++. Итак, вы на самом деле не используете C ++; вы используете Objective-C ++, который принимает большую часть C ++ в качестве входных данных (так же, как C ++ принимает большинство, но не весь C в качестве входных данных). Когда я говорю, что это не совсем C ++, рассмотрите файл C ++, который включает переменную с именем nil
(что является допустимым C ++), а затем попробуйте скомпилировать его как Objective-C ++.
У Свифта нет таких отношений. Это не надмножество C или C ++, и вы не можете напрямую использовать их в .swift
файле.
«Использование Swift с Cocoa и Objective-C» также говорит нам:
Вы не можете импортировать код C ++ непосредственно в Swift. Вместо этого создайте оболочку Objective-C или C для кода C ++.
.mm
своими файлами и (почти) сделать. Не так со Swift.
nil
, напримерint nil
Путаница может возникнуть из-за предположения, что простое изменение расширения файла с .m
на .mm
- это все, что вам нужно для соединения языков, хотя на самом деле ничего подобного не происходит. Это не то, .mm
что вызывает трение .cpp
, это .h
заголовок, который определенно не должен быть C++
заголовком.
В одном проекте вы можете смешивать C , C ++ , Objective-C , Objective C ++ , Swift и даже Assembly .
...Bridging-Header.h
: вы открываете C , Objective-C и Objective-C ++ для Swift, используя этот мост<ProductModuleName>-Swift.h
: автоматически предоставляет ваши классы Swift, отмеченные значком, @objc
для Objective-C.h
: это сложная часть, поскольку они неоднозначно используются для всех разновидностей C , ++ или нет, Objective или нет. Когда .h
не содержит ни одного C ++ ключевое слово, например class
, он может быть добавлен к ...Bridging-Header.h
, и подвергнет независимо функционировать соответствующие .c
или .cpp
функциональных возможностей он заявляет. В противном случае этот заголовок должен быть обернут либо в чистый C, либо в Objective-C API.В одном файле нельзя смешивать все 5. В одном исходном файле :
.swift
: Swift нельзя смешивать ни с чем.m
: Вы можете смешать Objective-C с C . ( @Vinzzz ).mm
: вы можете смешивать Objective-C с C ++ . Этот мост - Objective-C ++ . ( @Vinzzz )..c
: чистый C.cpp
: вы можете смешивать C ++ и Assembly ( @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
В частности, в этом примере вызывается Objective 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 (не виден 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"
что заголовок оборачивается в том месте, где он включен, а не #ifdef
в самом файле заголовка. Brilliant!
Я только что сделал небольшой пример проекта с использованием Swift, Objective-C и C ++. Это демонстрация того, как использовать сшивание OpenCV в iOS. OpenCV API - это C ++, поэтому мы не можем разговаривать с ним напрямую из Swift. Я использую небольшой класс-оболочку, файл реализации которого - Objective-C ++. Заголовок файл чист Objective-C, так что Swift может говорить с этим непосредственно. Вы должны позаботиться о том, чтобы косвенно не импортировать какие-либо файлы C ++ - ish в заголовки, с которыми взаимодействует Swift.
Проект находится здесь: https://github.com/foundry/OpenCVSwiftStitch
Вот моя попытка создать инструмент clang для автоматизации связи C ++ / swift. Вы можете создавать экземпляры классов C ++ из swift, наследовать от класса C ++ и даже переопределять виртуальные методы в swift.
Он проанализирует класс 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, который # включает C-совместимые заголовки C ++, помеченные как C, совместимые с трюком extern "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 для Linkage, а Linkage.mm имеет @implementation для .mm
А потом
Вы вставляете только #include "yourCpp.hpp"
файл Linkage.mm, а не файл Linkage.hpp.
Во многих онлайн-примерах / учебниках автор просто помещает @interface и @implementation в один и тот же файл .mm, как это часто бывает.
Это будет работать в очень простых примерах моста cpp, но,
Проблема в:
если ваш yourCpp.hpp имеет какие-либо функции C ++, которые обязательно будут (например, первая строка #include <something>
), то процесс завершится ошибкой.
Но если вы просто не имеют #include "yourCpp.hpp"
в Linkage заголовка файла (это нормально , чтобы иметь его в файле .mm, очевидно , вам нужно) - это работает.
Опять же, это, к сожалению, только один совет во всем процессе.
Если это кому-то будет полезно, у меня также есть краткое руководство по вызову простой статической библиотеки C ++ из простой утилиты командной строки Swift. Это действительно простое доказательство концептуального фрагмента кода.
Никакого Objective-C, только Swift и C ++. Код в библиотеке C ++ вызывается оболочкой C ++, которая реализует функцию с внешней связью "C". Затем эта функция упоминается в заголовке моста и вызывается из Swift.
Я даю ссылку на SE-0038 на официальном ресурсе, который описывается как « В нем содержатся предложения по изменениям и видимым пользователям улучшения языка программирования Swift.
На сегодняшний день статус таков, что это запрос функции, который был принят, но еще не запланирован.
Эта ссылка предназначена для того, чтобы направить всех, кто ищет эту функцию, в правильном направлении.