От Си++ к Свифт
2023-09-20 12:17На днях компилятор Свифт обновился до версии 5.9, и теперь мы имеем совместимость между Свифтом и Си++. Покажу пример вызова Си++ из кода Свифт.
Создадим тривиальный проект на Swift типа "Hello World". Сразу скомпилируем и запустим.
Создадим тривиальный проект на Swift типа "Hello World". Сразу скомпилируем и запустим.
Теперь перекурочим проект, чтобы из Swift вызывался код на Си++. Проект состоит из двух файлов:$ mkdir Demo
$ cd Demo
$ swift package init --type executable
$ swift run
Building for debugging...
[3/3] Linking Demo
Build complete! (0.56s)
Hello, world!
В файле Package.swift находится описание проекта. Это такой как бы Makefile, но попроще. Проект логически состоит из отдельных компонентов, называемых targets. Эти targets могут быть на разных языках. Отредактируем файл: добавим target "HelloCxx", укажем зависимости и разрешим совместимость с Си++. Было:$ tree
.
├── Package.swift
└── Sources
└── main.swift
Стало: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"),
]
)
В файле main.swift находится основной код приложения. Преобразуем его в отдельный target, для этого переместим в новую папку Demo.import PackageDescription
let package = Package(
name: "Demo",
targets: [
.target(name: "HelloCxx"),
.executableTarget(
name: "Demo",
dependencies: ["HelloCxx"],
swiftSettings: [.interoperabilityMode(.Cxx)]
),
]
)
Отредактируем файл: вместо выдачи строки непосредственно, вызовем код на Си++ и получим строку из него. Было:$ mkdir Sources/Demo
$ mv Sources/main.swift Sources/Demo
Стало:print("Hello, world!")
Теперь добавим target HelloCxx на языке Си++. Создадим два файла, Sources/HelloCxx/include/HelloCxx.h:import HelloCxx
let hello = HelloCxx()
let message = String(hello.message())
print(message)
и Sources/HelloCxx/HelloCxx.cpp:#include <string>
class HelloCxx {
public:
std::string message() const;
};
Получилась такая иерархия файлов:#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!