├── Package.swift ├── Sources ├── CPPExample │ ├── example.cc │ └── include │ │ ├── example.h │ │ └── module.modulemap └── Example │ └── Basic.swift └── Tests ├── ExampleTests ├── Basic.swift └── XCTestManifests.swift └── LinuxMain.swift /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.1 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Example", 7 | products: [ 8 | .library( 9 | name: "CPPExample", 10 | targets: ["CPPExample"]), 11 | .library( 12 | name: "Example", 13 | targets: ["Example"]), 14 | ], 15 | targets: [ 16 | .target( 17 | name: "CPPExample", 18 | dependencies: [] 19 | ), 20 | .target( 21 | name: "Example", 22 | dependencies: ["CPPExample"], 23 | // Note: These flags are to allow importing CPPXLA, it must be importted as 24 | // @_implementationOnly or it will conflict with other headers. 25 | swiftSettings: [.unsafeFlags(["-Xfrontend", "-enable-cxx-interop"])] 26 | ), 27 | .testTarget( 28 | name: "ExampleTests", 29 | dependencies: ["Example"] 30 | ), 31 | ] 32 | ) 33 | -------------------------------------------------------------------------------- /Sources/CPPExample/example.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "example.h" 5 | 6 | void example::MyStruct::dump() { 7 | fprintf(stderr, "MyStruct(a: %d, b: %d, c: %d)\n", a, b, c); 8 | } 9 | -------------------------------------------------------------------------------- /Sources/CPPExample/include/example.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace example { 4 | template 5 | class Silly { 6 | public: 7 | T c; 8 | }; 9 | 10 | class MyStruct : public Silly { 11 | public: 12 | int a; 13 | int b; 14 | 15 | void dump(); 16 | }; 17 | } 18 | 19 | using SwiftMyStruct = example::MyStruct; 20 | SwiftMyStruct* silly(); 21 | 22 | inline SwiftMyStruct* newMyStruct() { return new example::MyStruct; } 23 | inline void dumpMyStruct(SwiftMyStruct* ptr) { ptr->dump(); } 24 | inline void setMyStructC(SwiftMyStruct* ptr, int value) { ptr->c = value; } 25 | inline int getMyStructC(SwiftMyStruct* ptr) { return ptr->c; } 26 | inline void cppDelete(SwiftMyStruct* ptr) { delete ptr; } 27 | -------------------------------------------------------------------------------- /Sources/CPPExample/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module CPPExample { 2 | export * 3 | header "example.h" 4 | } 5 | -------------------------------------------------------------------------------- /Sources/Example/Basic.swift: -------------------------------------------------------------------------------- 1 | // You cannot safely use the types in CPPExample in the public interface 2 | // of this module. This is because downstream modules would need to import 3 | // CPPExample, but those modules could also import a c-module. The clang compiler 4 | // is only able to operate in one mode or the other. Thus, you can only 5 | // depend on modules compiled in one form or the other. 6 | @_implementationOnly import CPPExample 7 | 8 | extension SwiftMyStruct { 9 | mutating func dump() { 10 | dumpMyStruct(&self) 11 | } 12 | var c : Int32 { 13 | mutating get { 14 | getMyStructC(&self) 15 | } 16 | set { 17 | setMyStructC(&self, newValue) 18 | } 19 | } 20 | } 21 | 22 | public func doExampleFunc() { 23 | let tmp = newMyStruct()! 24 | tmp.pointee.a = 5 25 | tmp.pointee.b = 20 26 | tmp.pointee.c = 35 27 | tmp.pointee.dump() 28 | dumpMyStruct(tmp) 29 | cppDelete(tmp) 30 | } 31 | -------------------------------------------------------------------------------- /Tests/ExampleTests/Basic.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Example 3 | 4 | final class BasicTests: XCTestCase { 5 | func testExample() { 6 | doExampleFunc() 7 | } 8 | 9 | static var allTests = [ 10 | ("testExample", testExample), 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /Tests/ExampleTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(BasicTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import ExampleTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += ExampleTests.allTests() 7 | XCTMain(tests) 8 | --------------------------------------------------------------------------------