Spec-Zone.ru › Swift

Настройка проектов Swift и C++ с использованием смешанных языков

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

  • Swift Package Manager
  • Xcode

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

Использование Swift Package Manager для смешивания Swift и C++

Swift Package Manager позволяет коду Swift использовать C++ API в Swift.

Swift Package Manager пока не поддерживает использование Swift API в C++.

Включение совместимости с C++ в целевом пакете

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

let package = Package(
    name: "LibraryThatUsesCxx",
    products: [
        .library(
            name: "libraryUsesCxx",
            targets: ["libraryUsesCxx"])
    ],
    targets: [
        .target(
            name: "libraryUsesCxx",
            swiftSettings: [.interoperabilityMode(.Cxx)])
    ]
)

Импорт заголовков из целевого пакета C++

Swift импортирует заголовки C++ с использованием модулей Clang. Swift Package Manager может автоматически сгенерировать файл карты модуля для целевого объекта C++, содержащий заголовок umbrella. Сгенерированный файл карты модуля позволяет целевому объекту Swift, зависящему от такого целевого объекта C++, импортировать заголовки C++ из такого целевого объекта.

Заголовок umbrella должен содержать список директив #include, которые включают другие общедоступные заголовки C++ целевого объекта. Поддерживаемые типы и функции C++, объявленные в заголовках, перечисленных в заголовке umbrella, могут использоваться в Swift после импорта модуля Clang, представленного сгенерированной картой модуля, в Swift.

Заголовок umbrella, используемый целевым объектом C++, должен:

  • Использовать имя целевого объекта C++ (с дополнительным расширением) в качестве имени файла
  • Располагаться в каталоге общедоступных заголовков целевого объекта

Подкаталог include является стандартным каталогом общедоступных заголовков целевого объекта. Свойство publicHeadersPath можно использовать для указания альтернативного пути для общедоступных заголовков целевого объекта.

Например, следующий пакет Swift создает Swift утилиту командной строки, использующую C++ библиотеку:

let package = Package(
    name: "CommandLineSwiftToolUsesCxx",
    products: [
        .library(
            name: "cxxLibrary",
            targets: ["cxxLibrary"]),
        .executable(
            name: "swiftCLITool",
            targets: ["swiftCLITool"])
    ],
    targets: [
        .target(
            name: "cxxLibrary"),
        .executableTarget(
            name: "swiftCLITool",
            dependencies: ["cxxLibrary"],
            swiftSettings: [.interoperabilityMode(.Cxx)])
    ]
)

Swift Package Manager автоматически сгенерирует карту модулей для C++ библиотеки в этом пакете, так как в исходных кодах найдётся заголовок umbrella:

Sources
├── swiftCLITool
└── cxxLibrary
    ├── include
    │   ├── cxxLibrary.h   [This is the umbrella header]
    │   └── classImpl.h
    ├── cxxLibrary.cpp
    └── classImpl.cpp

Заголовок umbrella cxxLibrary.h содержит некоторые объявления и также включает другие заголовки в целевом объекте C++:

// Header file `cxxLibrary.h`
#pragma once

#include <classImpl.h>

Код Swift в swiftCLITool может напрямую импортировать cxxLibrary:

import cxxLibrary

После этого все поддерживаемые C++ API, объявленные в заголовке файла classImpl.h, будут доступны в Swift.

Пакеты, которые обеспечивают совместимость с C++

Для включения совместимости с C++ для целевого объекта Swift Package Manager потребуются и другие целевые объекты, которые зависят от данного целевого объекта.

Включение совместимости с C++ является изменением, вносящим разрывы в существующий пакет, и поэтому оно должно осуществляться только в новой основной версии semver. Пожалуйста, увеличьте основную версию пакета, когда вы включаете совместимость с C++!

Если вы хотите создать пакет с целевым объектом, который обеспечивает совместимость с C++, мы рекомендуем:

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

Смешивание Swift и C++ с использованием Xcode

Xcode 15 поддерживает проекты Swift и C++ с использованием смешанных языков. В этом разделе описано, как использовать C++ API из Swift и Swift API из C++ в Xcode.

Подробности о том, как использовать совместимость с C++ в Xcode, можно узнать из сессии WWDC 2023 «Смешивание Swift и C++». Также доступны для загрузки следующие два примерных проекта Xcode:

  • Смешивание Swift и C++ в рамках одного целевого объекта фреймворка
  • Использование C++ API из Swift и Swift API из C++ в разных целевых объектах

Включение совместимости с C++ в Xcode

Параметр сборки Xcode «Взаимодействие C++ и Objective-C» может быть установлен на «C++ / Objective-C++» для включения совместимости с C++ для определённой целевой сборки. Включение совместимости с C++ позволяет:

  • Смешивать Swift и C++ в одном целевом объекте.
  • Использовать C++ и Objective-C++ API из импортированных целевых объектов фреймворков.
  • Использовать общедоступные Swift API фреймворка из кода C++ или Objective-C++ в другом целевом объекте.

Смешивание Swift и C++ в одном целевом объекте Xcode

Xcode позволяет смешивать Swift и C++ или Objective-C++ в рамках одного фреймворка или целевого приложения. Поддерживаемые типы и функции C++, объявленные в общедоступном заголовке целевого объекта фреймворка, могут использоваться из кода Swift в том же целевом объекте. Целевые объекты приложений должны использовать заголовок перевода, чтобы сделать типы и функции C++ целевого объекта доступными для кода Swift в том же целевом объекте приложения. Код Swift в целевом объекте приложения может использовать такие C++ API, как только в заголовок перевода будет добавлена директива #include, включающая заголовок C++ приложения, который объявляет эти API.

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

// FibonacciCxx.cpp [Fibonacci target]

#include <Fibonacci/Fibonacci-Swift.h>
// You can now use the exposed Swift APIs from Fibonacci.

Использование C++ API импортированного целевого объекта фреймворка

Поддерживаемые функции и типы C++, объявленные в общедоступном заголовке C++ целевого объекта фреймворка Xcode, могут использоваться из кода Swift в других целевых объектах. Целевой объект, который хочет использовать C++ API из другого целевого объекта фреймворка, должен добавить фреймворк в список зависимостей. Файл Swift исходного кода в таком целевом объекте может затем импортировать фреймворк и использовать C++ API в Swift.

Например, общедоступные C++ API фреймворка *ForestLib* могут использоваться из файла Swift исходного кода в целевом объекте приложения *ForestViewer*, после того как Swift файл импортирует фреймворк *ForestLib*:

// TreeView.swift [ForestViewer App target]

import ForestLib

// You can now use the supported C++ APIs from ForestLib.

Использование Swift API импортированного целевого объекта фреймворка

Поддерживаемые и опубликованные общедоступные Swift API целевого объекта фреймворка Xcode могут использоваться из кода C++ и Objective-C++ в других целевых объектах. Целевой объект, который хочет использовать Swift API из другого целевого объекта фреймворка, должен добавить фреймворк в список зависимостей. Файл исходного кода C++ или Objective-C++ в таком целевом объекте может затем включить сгенерированный заголовок фреймворка и использовать Swift API в C++ или Objective-C++.

Например, общедоступные экспонированные Swift API фреймворка *StorageProvider* могут использоваться из файла Objective-C++ исходного кода в целевом объекте приложения *SafeStorage*, после того как файл Objective-C++ исходного кода включит следующий сгенерированный заголовок:

// StorageAccess.mm [SafeStorage App target]

#include <StorageProvider/StorageProvider-Swift.h>

// You can now use the exposed Swift APIs from StorageProvider.

Смешивание Swift и C++ с использованием других систем сборки

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

Включение взаимодействия с C++ в компиляторе Swift

Флаг сборки -cxx-interoperability-mode= используется для включения взаимодействия с C++ в компиляторе Swift. Он получает значение совместимости версии взаимодействия. В настоящее время поддерживается только значение default. Значение default подразумевает, что версия совместимости взаимодействия, используемая Swift, соответствует версии языка Swift.

Импорт модуля C++ Clang при непосредственном вызове компилятора

Следующий флаг сборки позволяет Swift находить заголовки C++:

  • -I <path>: Этот флаг указывает Swift, что он должен искать импорты в директории, указанной заданным путем. Этот путь должен содержать файл module.modulemap, когда вы хотите импортировать модуль C++ Clang в Swift.

Флаг -Xcc используется для передачи дополнительных настроек сборки C++ компилятору C++ Clang, встроенному в компилятор Swift. Например, вы можете использовать флаг -std= Clang для импорта заголовков C++, требующих C++20, в Swift:

swiftc ... -Xcc -std=c++20 ...

Объединив все вместе, следующий вызов компилятора Swift позволяет скомпилировать файл Swift, который импортирует модуль Clang, файл карты модулей которого находится в каталоге include:

swiftc main.swift -cxx-interoperability-mode=default -I include -o main

Генерация заголовка C++ с экспонированными API Swift

Флаг передней части Swift -emit-clang-header-path может использоваться для выдачи сгенерированного заголовка при экспонировании API Swift для C++ при построении кода Swift в системе сборки, которая не предоставляет автоматической поддержки генерации файла заголовка с экспонированными API.

Следующий вызов компилятора Swift создает сгенерированный файл заголовка для модуля SwiftModule, состоящего из двух исходных файлов, a.swift и b.swift:

swiftc -frontend -typecheck \
       /sources/a.swift /sources/b.swift -module-name SwiftModule \
       -cxx-interoperability-mode=default \
       -emit-clang-header-path SwiftModule-Swift.h

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/project-build-setup

Spec-Zone.ru

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