Swift Package Manager now supports packages with Swift, C, C++, Objective-C and Objective-C++. It should be available in the next toolchain from trunk (latest right now is 9th May, 2016).
To demonstrate how they can be used lets look at two very simple packages.
A Package with Objective-C and Swift.
This package contains 3 modules:
- objc: an Objective-C and C mixed library.
- objc-exec: an Objective-C executable.
- swift-exec: a Swift executable.
The layout of the package:
├── Package.swift
└── Sources
├── objc
│ ├── include
│ │ ├── objc.h
│ │ └── sea.h
│ ├── objc.m
│ └── sea.c
├── objc-exec
│ └── main.m
└── swift-exec
└── main.swift
Package.swift
import PackageDescription
let package = Package(
name: "Objc",
targets: [Target(name: "objc-exec", dependencies:["objc"]),
Target(name: "objxec", dependencies:["objc"]),
Target(name: "swift-exec", dependencies:["objc"])]
)
objc:
sea.h
:
int one();
sea.c
:
#include "include/sea.h"
int one() {
return 1;
}
objc.h
:
#import <Foundation/Foundation.h>
#include "sea.h"
@interface Foo: NSObject
- (int)foo;
@end
objc.m
:
#import "include/objc.h"
@implementation Foo
- (int)foo {
return 3 + one();
}
@end
So basically we have an Obj-C class Foo
with a method foo
which sums 3 and result of one()
which is C function.
objc-exec:
main.m
:
#import <Foundation/Foundation.h>
#import "objc.h"
int main() {
int result = [[[Foo alloc] init] foo] + one();
printf("Hello from Objc %d", result);
return 0;
}
Here we use the class we defined in objc module to print the result.
swift-exec:
main.swift
:
import objc
print("\(Foo().foo() + one())")
And similar executable in swift.
Compile and run:
$ swift build
Compile objc sea.c
Compile objc objc.m
Linking objc
Compile Swift Module 'swift_exec' (1 sources)
Compile objc-exec main.m
Linking objc-exec
Linking .build/debug/swift-exec
$ .build/debug/objc_exec
Hello from Objc 5
$ .build/debug/swift_exec
5
Profit!
A Package with Cpp and Swift.
This package will have 4 modules:
- cpplib: a C++ library.
- cwrapper: a C wrapper to the C++ library since we can’t import C++ into swift.
- cpp-exec: a C++ executable.
- swift-exec: a Swift executable.
Layout:
├── Package.swift
└── Sources
├── cpp-exec
│ └── main.cpp
├── cpplib
│ ├── cpplib.cpp
│ └── include
│ └── cpplib.h
├── cwrapper
│ ├── cwrapper.cpp
│ └── include
│ └── cwrapper.h
└── swift-exec
└── main.swift
Package.swift:
import PackageDescription
let package = Package(
name: "Objc",
targets: [Target(name: "cpp-exec", dependencies:["cpplib"]),
Target(name: "cwrapper", dependencies:["cpplib"]),
Target(name: "swift-exec", dependencies:["cwrapper"]),
]
)
cpplib:
cpplib.h
:
namespace cpplib {
int five();
}
cpplib.cpp
:
#import "include/cpplib.h"
namespace cpplib {
int five() {
return 5;
}
}
Just a simple function five()
inside namespace cpplib
.
cwrapper:
cwrapper.h
:
#ifdef __cplusplus
extern "C" {
#endif
int cwrapperfive();
#ifdef __cplusplus
}
#endif
cwrapper.cpp
:
#import "include/cwrapper.h"
#import "cpplib.h"
int cwrapperfive() {
return cpplib::five();
}
Wrap the cpp library function into a C function so it can be used by swift.
cpp-exec:
main.cpp
:
#include <iostream>
#include "cpplib.h"
int main() {
std::cout << cpplib::five();
return 0;
}
call and print result of the function inside C++ module.
swift-exec:
main.swift
:
import cwrapper
print(cwrapperfive())
Call the method from the C wrapper module.
Compile and run:
$ swift build
Compile cpplib cpplib.cpp
Linking cpplib
Compile cwrapper cwrapper.cpp
Compile cpp-exec main.cpp
Linking cwrapper
Compile Swift Module 'swift_exec' (1 sources)
Linking .build/debug/swift-exec
Linking cpp-exec
$ .build/debug/cpp_exec
5
$ .build/debug/swift_exec
5
If you have any doubts feel free to ping me: @aciidb0mb3r.