2 min read

Calling C code from Swift

Swift has excellent interoperability with C . We can call C code directly in Swift without needing a bridging header as we do when mixing with Objective-C code. So, let’s explore how this works with a simple example.

Setting up the project

Start by creating a new Swift project using Swift Package Manager:

mkdir CSwift && cd CSwift
swift package init --type executable --name CSwift

We’ll need to organize our project structure to include both Swift and C code. The structure should look like this:

├── Package.swift
└── Sources
    ├── CSwift
    │   └── main.swift
+   └── cmath
+       ├── include
+       │   ├── math.h
+       │   └── module.modulemap
+       └── math.c

Writing the C code

Let’s keep it simple by creating just two basic arithmetic functions. Start by defining the function signatures in the header file math.h:

#ifndef math_h
#define math_h

int add(int a, int b);
int multiply(int a, int b);

#endif /* math_h */

Now provide the actual implementation for the functions in the math.c:

#include "math.h"

int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

To make our C code importable in Swift, define it in the module.modulemap:

module cmath {
    header "math.h"
    export *
}

Updating Package.swift

Since we’re using Swift Package Manager, we must define our cmath module in the Package.swift and add it as a dependency to the project:

// swift-tools-version: 6.1

import PackageDescription

let package = Package(
    name: "CSwift",
    targets: [
+       .target(name: "cmath"),
        .executableTarget(
            name: "CSwift",
+           dependencies: ["cmath"]
        )
    ]
)

Testing it out

Now that everything is set up, we can import and use our C code in Swift like this:

import cmath

let additionResult = add(1, 2)
let multiplicationResult = multiply(1, 2)

print(additionResult)
print(multiplicationResult)

Run it and see the results:

swift run

# Output:
# 3
# 2

And that’s it! We can use this approach to integrate existing C libraries or write performance-critical code in C while keeping everything else in Swift.

SwiftCInteroperability