Spec-Zone.ru › Swift

Поддерживаемые возможности и ограничения межплатформенного взаимодействия C++

Swift поддерживает двустороннее взаимодействие с C++. На этой странице описываются поддерживаемые на данный момент функции взаимодействия с C++. Также здесь обсуждаются ограничения текущей поддержки межплатформенного взаимодействия с C++. Кроме того, здесь приведены ограничения, связанные с поддержкой взаимодействия с C++.

Взаимодействие с C++ — активно развивающаяся функция Swift. Определённые аспекты его дизайна и функциональности могут измениться в будущих версиях Swift, поскольку сообщество Swift собирает отзывы об использовании межплатформенного взаимодействия C++ в смешанных кодовых базах Swift и C++. Эта страница будет обновляться всякий раз, когда новая версия Swift изменяет поддерживаемые функции взаимодействия с C++.

Поддержка платформ

Взаимодействие с C++ поддерживается для разработки и развертывания на всех платформах, поддерживаемых Swift.

Минимальная версия развертывания для приложений со смешанными языками

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

Минимальная версия развертывания для ссылочных типов, импортированных из C++

В таблице ниже показана минимальная версия ОС, для которой можно развернуть приложение со смешанным кодом Swift и C++, использующее классы или структуры C++, которые становятся ссылками. Любая платформа развертывания, не указанная в таблице ниже, поддерживается автоматически, поэтому импортированные ссылочные типы не накладывают дополнительных требований к версии развертывания для таких платформ, как Ubuntu или CentOS.

Платформа, на которой выполняется приложение Swift Минимальная версия развертывания
macOS 13.3
iOS 16.4
watchOS 9.4
tvOS 16.4

Поддержка компилятора

Взаимодействие с C++ поддерживается в Swift 5.9 и выше.

Поддержка Swift двустороннего взаимодействия основана на заголовке, сгенерированном компилятором Swift, который затем может быть включён кодом C++, желающим использовать Swift API. Этот заголовок использует специфические для Swift расширения компилятора, которые поддерживаются только следующими компиляторами C++:

  • Clang (начиная с LLVM 11 и выше)
  • Apple Clang

Код C++, скомпилированный другими компиляторами, не может вызывать Swift-функции или использовать Swift-типы из C++.

Поддержка стандартной библиотеки C++

Компилятор Swift использует стандартную библиотеку C++ платформы при взаимодействии с C++. В этой таблице показано, какая стандартная библиотека C++ используется при построении кода Swift для определённой платформы развертывания:

Платформа, на которой выполняется приложение Swift Стандартная библиотека C++ по умолчанию
Платформы Apple libc++
Ubuntu, CentOS, Amazon Linux libstdc++
Windows Стандартная библиотека C++ Microsoft (msvcprt)

Swift в настоящее время не поддерживает выбор альтернативной стандартной библиотеки для платформ, поддерживающих альтернативные стандартные библиотеки. Например, вы не можете использовать libc++ при построении кода Swift для Ubuntu, даже если libc++ может использоваться при построении кода C++ для Ubuntu.

Смешанный код Swift и C++ должен использовать одну и ту же стандартную библиотеку C++.

Использование взаимодействия с C++ требует компилятора с включённой поддержкой стандарта C++14 или более новой версии. Swift позволяет изменить, какую версию стандарта C++ использовать; однако, заголовки библиотек C++, используемые из Swift, также должны соответствовать выбранному стандарту C++. При использовании двустороннего взаимодействия программы необходимо компилировать с поддержкой C++14, так как сгенерированный C++ интерфейс для модуля Swift использует возможности C++14.

Настройка версии стандарта C++

Вот как установить версию стандарта C++, используемого для взаимодействия компилятором Swift:

  • При компиляции зависимостей пакета версия стандарта C++ может быть настраиваема в Package.swift с помощью параметра cxxLanguageStandard в вашем Package(...).
  • Для целей Xcode вы можете выбрать используемый стандарт C++ из настроек «Диалект языка C++» во вкладке «Настройки сборки».
  • Если вы используете другую систему сборки или вызываете компилятор Swift напрямую из командной строки, вы можете указать версию стандарта C++ с помощью опции -Xcc -std=, например, -Xcc -std=c++20.

Поддерживаемые API C++

Поддерживаемые в Swift функции C++

Swift поддерживает вызов большинства нешаблонных:

  • Функций верхнего уровня
  • Функций внутри пространств имён
  • Член-функций, как экземпляров, так и статических
  • Виртуальных член-функций типов C++, которые становятся ссылками
  • Конструкторов
  • Операторов
    • Арифметических операторов, таких как operator+, operator-, operator*
    • Оператора прединкремента operator++ представлен как func successor() -> Self
    • Оператора вызова T operator(Param p) представлен как func callAsFunction(p: Param) -> T
    • Оператора преобразования булевого литерала operator bool представлен как удобный инициализатор Bool(fromCxx:)

Функции и конструкторы, использующие типы r-value ссылок, пока недоступны в Swift.

Swift поддерживает вызов некоторых шаблонных функций C++. Любая функция или шаблон функции, использующие зависимый тип в своей сигнатуре или универсальную ссылку (T &&), недоступна в Swift. Любой шаблон функции с параметрами шаблона, отличными от типов, недоступен в Swift. Шаблоны функций с переменным числом аргументов недоступны в Swift.

Функция C++, тип возвращаемого значения которой не поддерживается в Swift, или с параметром, тип которого не поддерживается в Swift, недоступна в Swift.

Если параметр функции C++ имеет значение по умолчанию, параметр также будет иметь значение по умолчанию в Swift, если:

  • Функция не является конструктором
  • Параметр не является inout в Swift
  • Параметр не является указателем
  • Параметр не является константной ссылкой

Поддерживаемые в Swift типы C++

  • Примитивные типы, такие как int и bool
  • Указатели
  • C++ ссылки, за исключением параметров r-value ссылок/универсальных ссылок
  • Алиасы типов, только если базовый тип поддерживается в Swift
  • Копируемые структуры и классы
  • Перемещаемые некопируемые структуры и классы
  • Перечисления, включая перечисления со областью действия (enum class)

Типы C++, которые становятся значениями в Swift, могут создаваться и передаваться по значению.

Типы C++, которые становятся ссылками в Swift, не могут быть созданы напрямую кодом Swift. Они могут свободно передаваться между Swift и C++.

Типы C++, определённые внутри C++ namespace, доступны в Swift.

Шаблоны классов и структур напрямую недоступны в Swift. Инициализированные специализации классов или структур шаблонов доступны в Swift. Код Swift может получить доступ к типам специализации шаблона, используя алиас типа, определённый в заголовке C++.

Публичные члены данных структуры или класса C++ доступны в Swift, когда тип такого члена данных поддерживается в Swift.

Поддерживаемые в Swift типы стандартной библиотеки C++

Следующие типы стандартной библиотеки C++ поддерживаются в Swift:

  • std::string, std::u16string, std::u32string
  • Специализации std::pair
  • Специализации std::vector
  • Специализации std::map и std::unordered_map
  • Специализации std::set, std::multiset и std::unordered_set
  • Специализации std::optional
  • Специализации std::shared_ptr
  • Специализации std::array

Другие типы стандартной библиотеки, такие как std::unique_ptr, std::function и std::variant, пока не поддерживаются в Swift.

Другие возможности C++ обрабатываемые Swift

Исключения C++

Swift может взаимодействовать с кодом C++, который вызывает исключения. Однако Swift не поддерживает перехват исключений C++. Вместо этого работающая программа завершается с ошибкой fatal, когда исключение C++, которое не перехвачено кодом C++, достигает кода Swift.

Строгое завершение программы Swift для любых неперехваченных исключений в настоящее время не поддерживается при выполнении кода Swift, построенного с помощью Swift на Windows. Любая программа смешанного языка, работающая на Windows, всегда должна завершаться, когда исключение C++ распространяется через код Swift, поскольку стек программы разворачивается. Любая попытка восстановиться из такого неперехваченного исключения может привести к неопределенному поведению в вашей программе.

Атрибуты доступности Clang

C++ API, аннотированные атрибутами доступности Clang, получают те же аннотации доступности в Swift.

Поддерживаемые Swift API

В этом разделе описывается, какие Swift API экспонируются для C++ в сгенерированном заголовке.

Swift структуры, поддерживаемые C++

Swift может сгенерировать представление C++ для большинства основных Swift структур. Следующие Swift структуры пока не поддерживаются:

  • Структуры нулевого размера, которые не имеют хранимых свойств
  • Некопируемые структуры
  • Обобщенные структуры с обобщенными ограничениями или более чем тремя обобщенными параметрами или имеющие вариативные обобщения

В настоящее время Swift не экспонирует вложенные структуры для C++.

Swift классы и акторы, поддерживаемые C++

Swift может сгенерировать представление C++ для большинства основных Swift классов и акторов. Следующие Swift классы пока не поддерживаются:

  • Обобщенные классы и акторы

В настоящее время Swift не экспонирует вложенные классы и акторы для C++.

Swift перечисления, поддерживаемые C++

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

  • Некопируемые перечисления
  • Обобщенные перечисления с обобщенными ограничениями или более чем тремя обобщенными параметрами или имеющие вариативные обобщения
  • Перечисления, у которых есть случай перечисления со связанным значением более чем одного
  • Косвенные перечисления

Кроме того, типы всех связанных значений перечисления должны быть представимыми в C++. Точный набор представимых типов описан ниже, в разделе, описывающем представимые параметры или возвращаемые типы.

В настоящее время Swift не экспонирует вложенные перечисления для C++.

Swift функции и свойства, поддерживаемые C++

Любая функция, свойство или инициализатор экспонируется в C++ только тогда, когда Swift может представить все её параметры и возвращаемые типы в C++. Тип параметра или возвращаемого значения может быть представлен в C++ только тогда, когда:

  • это поддерживаемая Swift структура/класс/перечисление, определённая в том же Swift модуле.
  • или это C++ структура/класс/перечисление, которое не помечено как тип ссылки.
  • или это один из поддерживаемых типов Swift стандартной библиотеки.
    • если это обобщенный тип, например Array, его обобщенные параметры должны быть связаны с одним из типов, перечисленных здесь.
  • или это UnsafePointer / UnsafeMutablePointer / Optional<UnsafePointer> / Optional<UnsafeMutablePointer>, указывающее на любой тип из трёх поддерживаемых категорий типов, перечисленных выше.

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

Кроме того, следующие Swift функции, свойства и инициализаторы пока не могут быть представлены в C++:

  • Асинхронные функции/свойства
  • Функции/свойства/инициализаторы, которые throw
  • Обобщённые функции/свойства/инициализаторы с обобщёнными ограничениями или вариативными обобщениями
  • Функции, возвращающие непрозрачный тип
  • Функции, возвращающие несколько значений
  • Функции/свойства/инициализаторы с атрибутом @_alwaysEmitIntoClient

Поддерживаемые Swift типы стандартной библиотеки

Swift может представить следующие типы Swift стандартной библиотеки в C++:

  • Примитивные типы, такие как Bool, Int, Float и их C аналоги, такие как CInt
    • Полный список поддерживаемых примитивных типов указан ниже.
  • Типы указателей, такие как OpaquePointer, UnsafePointer, UnsafeMutablePointer, UnsafeRawPointer и UnsafeMutableRawPointer
  • String тип
  • Array тип
  • Optional тип

Для получения более подробной информации об использовании Swift типов, таких как String в C++, ознакомьтесь с разделом, описывающим, как использовать типы Swift стандартной библиотеки из C++.

Обратите внимание, что кортежи Swift в настоящее время не поддерживаются в C++.

Список примитивных Swift типов, поддерживаемых C++

В этой таблице перечислены примитивные типы Swift, определенные в стандартной библиотеке Swift, которые могут быть представлены в C++:

END_OF_DOCUMENT_MARKER
Swift Type Corresponding C++ type
Bool bool
Int swift::Int
UInt swift::UInt
Int8 int8_t
Int16 int16_t
Int32 int32_t
Int64 int64_t
UInt8 uint8_t
UInt16 uint16_t
UInt32 uint32_t
UInt64 uint64_t
Float float
Double double
Float32 float
Float64 double
CBool bool
CChar char
CWideChar wchar_t
CChar16 char16_t
CChar32 char32_t
CSignedChar signed char
CShort short
CInt int
CLong long
CLongLong long long
CUnsignedChar unsigned char
CUnsignedShort unsigned short
CUnsignedInt unsigned int
CUnsignedLong unsigned long
CUnsignedLongLong unsigned long long
CFloat float
CDouble double

Ограничения и пределы

В Swift есть некоторые известные ограничения, связанные с поддержкой взаимодействия с C++. В настоящее время они перечислены на GitHub.

Ограничения Swift Package Manager

Целевой Swift, который включает взаимодействие с C++ в Swift Package Manager требует, чтобы его зависимости также включали взаимодействие с C++. Статус этого ограничения отслеживается в проблеме Swift GitHub:

  • Swift должен предоставить поддержку внутренних импортов и устойчивости для всех платформ (которые могут быть включены в SwiftPM), чтобы разрешить модулям Swift зависеть от модулей C++ без требования, чтобы клиенты включали взаимодействие с C++

Ограничения производительности

Текущая поддержка Swift для типов контейнеров C++ не предоставляет явных гарантий производительности. Наиболее заметно, что Swift может выполнить глубокую копию коллекции, когда она используется в цикле for-in в Swift.

Следующая проблема отслеживает статус этого ограничения производительности:

  • Swift должен предоставить языковые возможности, которые позволят избежать копирования контейнера C++ при прохождении по нему в цикле for-in или при использовании методов коллекций, таких как map и filter

Совместимость с существующими кодовыми базами, которые используют API C или Objective-C в Swift

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

  • C++ использует более широкий набор ключевых слов, которые могут конфликтовать с существующими API C или Objective-C. Например, функция C, один из параметров которой назван class, не является допустимой функцией C++.
  • Существующие заголовки C или Objective-C могут попытаться импортировать другой модуль Clang внутри блока extern "C". Это не разрешается в режиме C++.

В таких случаях рекомендуется исправить эти проблемы в ваших заголовках C или Objective-C. Если эти заголовки поступают от зависимости, которой вы не управляете, вам следует сообщить об этой проблеме поставщику этих заголовков.

В некоторых существующих кодовых базах, использующих функции из стандартной библиотеки C платформы, могут возникнуть ошибки неоднозначности, связанные с тем, что такие функции также определены в стандартной библиотеке C++. Swift предпочитает использовать математические функции, такие как sin и pow из стандартной библиотеки C. Некоторые другие функции, о которых Swift не знает, всё ещё могут вызвать ошибку. В тех случаях, когда вы видите такую ошибку, связанную с неоднозначностью функции из стандартной библиотеки C платформы, вы можете разрешить её, используя явный квалификатор модуля из Swift при вызове такой функции.

The Swift Programming Language, Copyright © 2014-2025 Apple Inc.
Swift and the Swift logo are trademarks of Apple Inc.

Documentation for Swift 6.0.3


https://www.swift.org/documentation/cxx-interop/status

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API