docs/CppInteroperability/GettingStartedWithC++Interop.md
This document is designed to get you started with bidirectional API-level interoperability between Swift and C++.
module.modulemap, in this file create the module for your source code, and define your C++ header (requires cplusplus isn't required but it's convention for C++ modules, especially if they use C++ features).// In module.modulemap
module CxxTest {
header "CxxTest.hpp"
requires cplusplus
}
Add the C++ module to the include path and enable C++ interop:
Navigate to your project directory
In Project navigate to Build Settings -> Swift Compiler
Under Custom Flags -> Other Swift Flags add -cxx-interoperability-mode=default
Under Search Paths -> Import Paths add your search path to the C++ module (i.e, ./ProjectName/CxxTest).
This should now allow your to import your C++ Module into any .swift file.
//In ContentView.swift
import SwiftUI
import CxxTest
struct ContentView: View {
var body: some View {
Text("CxxTest function result: \(cxxFunction(7))")
.padding()
}
}
// In CxxTest.hpp
#ifndef CxxTest_hpp
#define CxxTest_hpp
int cxxFunction(int n);
#endif
// In CxxTest.cpp
#include "CxxTest.hpp"
int cxxFunction(int n) {
return n;
}
After creating your Swift package project, follow the steps Creating a Module to contain your C++ source code in your Source directory
CxxInteropSources/CxxInterop called main.swiftdependencies to the C++ Module, the path, source, and swiftSettings with unsafeFlags with the source to the C++ Module, and enable -cxx-interoperability-mode=default//In Package Manifest
import PackageDescription
let package = Package(
name: "CxxInterop",
platforms: [.macOS(.v12)],
products: [
.library(
name: "CxxTest",
targets: ["CxxTest"]),
.library(
name: "CxxInterop",
targets: ["CxxInterop"]),
],
targets: [
.target(
name: "CxxTest",
dependencies: []
),
.executableTarget(
name: "CxxInterop",
dependencies: ["CxxTest"],
path: "./Sources/CxxInterop",
sources: [ "main.swift" ],
swiftSettings: [.unsafeFlags([
"-I", "Sources/CxxTest",
"-cxx-interoperability-mode=default",
])]
),
]
)
//In main.swift
import CxxTest
public struct CxxInterop {
public func callCxxFunction(n: Int32) -> Int32 {
return cxxFunction(n: n)
}
}
print(CxxInterop().callCxxFunction(n: 7))
//outputs: 7
After creating your project follow the steps Creating a Module to contain your C++ source code
CMakeLists.txt file and configure for your projectadd_library invoke cxx-support with the path to the C++ implementation filetarget_include_directories with cxx-support and path to the C++ Module ${CMAKE_SOURCE_DIR}/Sources/CxxTestadd_executable to the specific files/directory you would like to generate source, withSHELL:-cxx-interoperability-mode=default.// In CMakeLists.txt
cmake_minimum_required(VERSION 3.18)
project(CxxInterop LANGUAGES CXX Swift)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS OFF)
add_library(cxx-support ./Sources/CxxTest/CxxTest.cpp)
target_compile_options(cxx-support PRIVATE
-fno-exceptions
-fignore-exceptions)
target_include_directories(cxx-support PUBLIC
${CMAKE_SOURCE_DIR}/Sources/CxxTest)
add_executable(CxxInterop ./Sources/CxxInterop/main.swift)
target_compile_options(CxxInterop PRIVATE
"SHELL:-cxx-interoperability-mode=default")
target_link_libraries(CxxInterop PRIVATE cxx-support)
//In main.swift
import CxxTest
public struct CxxInterop {
public static func main() {
let result = cxxFunction(7)
print(result)
}
}
CxxInterop.main()
In your project's directory, run cmake to generate the systems build files
To generate an Xcode project run cmake -GXcode
To generate with Ninja run cmake -GNinja
For more information on cmake see the 'GettingStarted' documentation: (https://github.com/swiftlang/swift/blob/main/docs/HowToGuides/GettingStarted.md)