На днях компилятор Свифт обновился до версии 5.9, и теперь мы имеем совместимость между Свифтом и Си++. Покажу пример вызова Си++ из кода Свифт.
Создадим тривиальный проект на Swift типа "Hello World". Сразу скомпилируем и запустим.
$ mkdir Demo
$ cd Demo
$ swift package init --type executable
$ swift run
Building for debugging...
[3/3] Linking Demo
Build complete! (0.56s)
Hello, world!
Теперь перекурочим проект, чтобы из Swift вызывался код на Си++. Проект состоит из двух файлов:
$ tree
.
├── Package.swift
└── Sources
└── main.swift
В файле Package.swift находится описание проекта. Это такой как бы Makefile, но попроще. Проект логически состоит из отдельных компонентов, называемых targets. Эти targets могут быть на разных языках. Отредактируем файл: добавим target "HelloCxx", укажем зависимости и разрешим совместимость с Си++. Было:
import PackageDescription
let package = Package(
name: "Demo",
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "Demo"),
]
)
Стало:
import PackageDescription
let package = Package(
name: "Demo",
targets: [
.target(name: "HelloCxx"),
.executableTarget(
name: "Demo",
dependencies: ["HelloCxx"],
swiftSettings: [.interoperabilityMode(.Cxx)]
),
]
)
В файле main.swift находится основной код приложения. Преобразуем его в отдельный target, для этого переместим в новую папку Demo.
$ mkdir Sources/Demo
$ mv Sources/main.swift Sources/Demo
Отредактируем файл: вместо выдачи строки непосредственно, вызовем код на Си++ и получим строку из него. Было:
print("Hello, world!")
Стало:
import HelloCxx
let hello = HelloCxx()
let message = String(hello.message())
print(message)
Теперь добавим target HelloCxx на языке Си++. Создадим два файла, Sources/HelloCxx/include/HelloCxx.h:
#include <string>
class HelloCxx {
public:
std::string message() const;
};
и Sources/HelloCxx/HelloCxx.cpp:
#include "HelloCxx.h"
std::string HelloCxx::message() const
{
return "Hello from C++ to Swift!";
}
Получилась такая иерархия файлов:
$ tree
.
├── Package.swift
└── Sources
├── Demo
│ └── main.swift
└── HelloCxx
├── HelloCxx.cpp
└── include
└── HelloCxx.h
Компилируем, запускаем:
$ swift run
Building for debugging...
[4/4] Linking Demo
Build complete! (2.87s)
Hello from C++ to Swift!
Это я раздумываю, какую пользу может нанести Свифт в моих делах. Как минимум ГЮИ на нём удобно делать. А бизнес-логику приложения оставить на Си++.