Можно ли смешивать Swift с С++? Как и файлы Objective - C.mm

Я только что изменил свои .m файлы на .mm и использовал С++. Есть ли способ сделать то же самое с Swift?

Ответ 1

Нет. Когда вы переключаетесь с .m на .mm, вы фактически переключаетесь с Objective-C на другой язык (который имеет много тонких различий) под названием Objective-C ++. Таким образом, вы не используете С++; вы используете Objective-C ++, который принимает большинство С++ в качестве входных данных (таким же образом, что С++ принимает большинство, но не все C в качестве входных данных). Когда я говорю это не совсем С++, рассмотрим файл С++, который включает переменную с именем nil (которая является законной С++), а затем попытайтесь скомпилировать ее как Objective-C ++.

Swift не имеет одинаковых отношений. Это не надмножество C или С++, и вы не можете напрямую использовать его в файле .swift.

"Использование Swift с Cocoa и Objective-C" также сообщает нам:

Вы не можете импортировать код С++ непосредственно в Swift. Вместо этого создайте оболочку Objective-C или C для кода С++.

Ответ 2

Путаница может исходить из предположения, что простое изменение расширения файла от .m до .mm - это все, что вам нужно, чтобы соединить языки, когда на самом деле он ничего не делает. Не .mm вызывает трение с .cpp, это заголовок .h, который должен положительно не быть заголовком C++.


Тот же проект: Да.

В том же проекте вы можете с радостью смешать C, С++, Objective-C, Objective С++, Swift и даже Assembly.

  • ...Bridging-Header.h: выставляете C, Objective-C и Objective-C ++ в Swift используя этот мост
  • <ProductModuleName>-Swift.h: автоматически выделяет классы Swift с @objc до Objective-C
  • .h: это сложная часть, поскольку они неоднозначно используются для всех ароматов C, ++ или нет, Цель или нет. Если .h не содержит одного ключевого слова С++, например class, его можно добавить в ...Bridging-Header.h и выставить любую функцию, соответствующую .c или .cpp, которые он объявляет. В противном случае этот заголовок должен быть обернут либо чистым C, либо Objective-C.

Тот же файл: Нет.

В том же файле вы не можете смешивать все 5. В том же исходном файле:

  • .swift: вы не можете смешивать Swift с чем-либо
  • .m: вы можете смешивать Objective-C с C. (@Vinzzz)
  • .mm: вы можете смешивать Objective-C с С++. Этот мост Objective-C ++. (@Vinzzz).
  • .c: pure C
  • .cpp: вы можете смешивать С++ и Сборка (@Vality)
  • .h: вездесущий и двусмысленный C, С++, Objective-C или Objective-C ++, поэтому ответ зависит от этого.

Ссылки

Ответ 3

Я написал простой проект Xcode 6, который показывает, как смешивать код С++, Objective C и Swift:

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

В частности, пример вызывает функцию Objective C и С++ из Swift.

Ключом является создание общего заголовка Project-Bridging-Header.h и размещение там заголовков Objective C.

Пожалуйста, загрузите проект в качестве полного примера.

Ответ 4

Я только что сделал небольшой проект с использованием Swift, Objective-C и С++. Это демонстрация того, как использовать строчку OpenCV в iOS. API OpenCV - это С++, поэтому мы не можем напрямую разговаривать с ним из Swift. Я использую небольшой класс-оболочку, файл реализации Objective-C ++. Файл заголовка чистый Objective-C, поэтому Swift может напрямую об этом поговорить. Вы должны заботиться о том, чтобы не косвенно импортировать любые файлы С++ - ish в заголовки, с которыми Swift взаимодействует.

Проект находится здесь: https://github.com/foundry/OpenCVSwiftStitch

Ответ 5

Вы также можете пропустить файл Objective-C. Просто добавьте файл заголовка C с исходным файлом .cpp. Имеют только C-декларации в файле заголовка и включают любой код С++ в исходный файл. Затем включите файл заголовка C в ** - Bridging-Header.h.

Следующий пример возвращает указатель на объект С++ (struct Foo), поэтому Swift может хранить в COpaquePointer вместо структуры 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 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;
}

Ответ 6

Здесь моя попытка инструмента clang для автоматизации С++/быстрой связи. Вы можете инициализировать классы С++ из swift, наследовать из класса С++ и даже переопределять виртуальные методы в swift.
Он проанализирует класс С++, который вы хотите экспортировать, и быстро сгенерируйте мост Objective-C/Objective-С++.

https://github.com/sandym/swiftpp

Ответ 7

Swift напрямую не совместим с С++. Вы можете обойти проблему, обернув свой код на С++ с помощью Objective-C и используя оболочку Objective C в Swift.

Ответ 9

Нет, не в одном файле.

Однако вы можете использовать С++ в Swift Projects без необходимости использования статической библиотеки или фреймворка. Как и другие пользователи, ключевым моментом является создание заголовка моста Objective-C, который # включает C-совместимые заголовки С++, которые помечены как C, совместимые с extern "C" {} трюк.

Видеоурок: https://www.youtube.com/watch?v=0x6JbiphNS4

Ответ 10

Другие ответы немного неточны. Вы можете смешать как 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;
}
// */

Ответ 11

Одна хитрость (из многих) в том, что

Вам нужен отдельный заголовок для файла моста obj- c++...

Вы не можете просто выбросить @interface и @implementation в один и тот же файл .mm, как это обычно делается.

Так что в вашем заголовочном файле моста у вас есть

#import "Linkage.hpp"

Linkage.hpp имеет @interface для Linkage, а Linkage.mm имеет @implementation для .mm

А затем

... вы на самом деле не #include "yourCpp.hpp" в Linkage.hpp.

Вы только помещаете #include "yourCpp.hpp" в файл Linkage.mm, не в файле Linkage.hpp.

Во многих онлайн-примерах/руководствах автор просто помещает @interface и @implementation в один и тот же файл .mm, как это часто делается.

Это будет работать в очень простых примерах cpp bridging, но,

Проблема в следующем:

если ваш yourCpp.hpp имеет какие-либо функции c++, которые он обязательно будет иметь (например, первую строку #include <something>), то процесс завершится неудачей.

Но если вы просто не не имеете #include "yourCpp.hpp" в заголовочном файле Linkage (это хорошо, если он есть в файле .mm, очевидно, вам нужно) - работы.

Опять же, к сожалению, это всего лишь один совет во всем процессе.

Ответ 12

В случае, если это полезно для всех, у меня также есть краткое руководство по вызову простой статической библиотеки С++ из тривиальной утилиты командной строки Swift. Это действительно убедительное доказательство концепции кода.

Нет Objective-C, только Swift и С++. Код в библиотеке С++ вызывается оболочкой С++, которая реализует функцию с внешней связью "C". Затем эта функция ссылается на заголовок моста и вызывается из Swift.

См. http://www.swiftprogrammer.info/swift_call_cpp.html

Ответ 13

Я предоставляю ссылку на SE-0038 в официальном ресурсе, описанном как Это поддерживает предложения по изменениям и видимым для пользователя усовершенствованиям языка Swift.

Статус на сегодняшний день заключается в том, что это запрос функции, который был принят, но еще не запланирован.

Эта ссылка предназначена для управления всеми, кто ищет эту функцию в правильном направлении.