Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds using Swift from C++ example #1454

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions examples/xplatform/swift_from_cxx/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
load("//swift:swift_library.bzl", "swift_library")

swift_library(
name = "landscape",
srcs = ["Landscape.swift"],
copts = ["-cxx-interoperability-mode=default"],
# Auto-generates landscape-Swift.h.
# It can be customized with generated_header_name.
generates_header = True,
module_name = "SwiftLandscape",
)

cc_binary(
name = "landscape_cxx_client",
srcs = ["landscape_cxx_client.cpp"],
deps = [":landscape"],
)
40 changes: 40 additions & 0 deletions examples/xplatform/swift_from_cxx/Landscape.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
public struct MountainPeak {
let name: String
let height: Float

public init(name: String, height: Float) {
self.name = name
self.height = height
}

public func printDescription() {
print("Peak: \(name), height: \(height)")
}
}

public class MountainRange {
let peaks: [MountainPeak]

public init(peaks: [MountainPeak]) {
self.peaks = peaks
}

public func printPeaks() {
print("Peaks in range:")
for peak in peaks {
peak.printDescription()
}
}
}

// Simple enum.
public enum VolcanoStatus {
case dormant
case active
}

// enum with associated values.
public enum LandmarkIdentifier {
case name(String)
case id(Int)
}
93 changes: 93 additions & 0 deletions examples/xplatform/swift_from_cxx/landscape_cxx_client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include <iostream>

#include "examples/xplatform/swift_from_cxx/landscape-Swift.h"

// The Swift module "SwiftLandscape" is imported as the C++ namespace
// "SwiftLandscape".

SwiftLandscape::VolcanoStatus invertVolcanoStatus(
SwiftLandscape::VolcanoStatus status) {
switch (status) {
case SwiftLandscape::VolcanoStatus::dormant:
// Returns `VolcanoStatus.active` case.
return SwiftLandscape::VolcanoStatus::active();
case SwiftLandscape::VolcanoStatus::active:
// Returns `VolcanoStatus.dormant` case.
return SwiftLandscape::VolcanoStatus::dormant();
}
}

void printLandmarkIdentifier(SwiftLandscape::LandmarkIdentifier identifier) {
switch (identifier) {
case SwiftLandscape::LandmarkIdentifier::name:
std::cout << (std::string)identifier.getName() << std::endl;
break;
case SwiftLandscape::LandmarkIdentifier::id:
std::cout << "unnamed landmark #" << identifier.getId() << std::endl;
break;
}
}

void structsAndClasses() {
std::cout << "----- Swift structs and classes in C++ -----" << std::endl;

// SwiftLandscape::MountainPeak is a Swift struct. But you must still use
// init(), because Swift initializers are not the same as C++
// constructors.
SwiftLandscape::MountainPeak mount_everest =
SwiftLandscape::MountainPeak::init("Mount Everest", 8848.0f);

// You can call a Swift struct member function from C++.
mount_everest.printDescription();

// Swift arrays are mapped to swift::Array<T> in C++.
auto peaks = swift::Array<SwiftLandscape::MountainPeak>::init();
{
SwiftLandscape::MountainPeak k2 =
SwiftLandscape::MountainPeak::init("K2", 8611.0f);
peaks.append(mount_everest);
peaks.append(k2);
}

SwiftLandscape::MountainRange himalayas =
SwiftLandscape::MountainRange::init(peaks);

himalayas.printPeaks();
}

void simpleEnums() {
std::cout << "----- Simple Swift enums -----" << std::endl;
auto dormant = SwiftLandscape::VolcanoStatus::dormant();
auto active = SwiftLandscape::VolcanoStatus::active();

std::cout << "dormant has C++ int value: "
<< static_cast<int>(SwiftLandscape::VolcanoStatus::cases::dormant)
<< std::endl;
std::cout << "active has C++ int value: "
<< static_cast<int>(SwiftLandscape::VolcanoStatus::cases::active)
<< std::endl;

auto inverted = invertVolcanoStatus(dormant);
std::cout << "inverted(dormant) == active? -> "
<< ((inverted == active) ? "true" : "false") << std::endl;
}

void enumsWithAssociatedTypes() {
std::cout << "----- Swift enums with associated types -----" << std::endl;
auto new_landmark_id = SwiftLandscape::LandmarkIdentifier::id(1234);
printLandmarkIdentifier(new_landmark_id);

auto new_landmark_name =
SwiftLandscape::LandmarkIdentifier::name("Eiffel Tower");
printLandmarkIdentifier(new_landmark_name);
}

int main(int argc, char* argv[]) {
structsAndClasses();

simpleEnums();

enumsWithAssociatedTypes();

return 0;
}