Use C library with Swift using Clang Modules (modulemap)

Introduction

Hello everyone. This is hiroakit, an iOS / tvOS app developer.

In this article, I will show you how to use a library written in C or C ++ in Swift.

The development environment used at the time of writing this article is as follows.

$ sw_vers                                                                               
ProductName:	Mac OS X
ProductVersion:	10.12.6
BuildVersion:	16G1114

$ xcrun -find xcode build
/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild

$ xcodebuild -version                                                                   
Xcode 9.2
Build version 9C40b

$ xcrun -find clang
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang

$ clang --version
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Motivation

You may want to use the C library (e.g, OpenJPEG) as a Swift framework.

In this article, I would like to proceed with the following C library for explanation.

- libExample.a
- include/Example.h
- include/ExampleEncoder.h

Suppose an app written in Swift wants to import and use this library in the framework.


import UIKit
import Example

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        ExampleEncoder.run(urlString: "https://www.example.com/", profile: "path/to/profile")
    }
}

In this case, when you wrap the C library in Swift into a framework, you need to prepare the .modulemap file as shown below.


framework module Example {
    umbrella header "Example.h"

    export *
    module * { export * }

    header "ExampleEncoder.h"
}

After adding this Example.framework on the app side, you need to set the path of that framework to the following setting items of the Xcode project.

What is a .modulemap file?

The .modulemap file is needed to tell Swift the header files used by the C library through Clang Modules.

The following shows the format of the .modulemap file. Describe using module map language.

[explicitopt] [frameworkopt] module module-id attributesopt {
    /* module-member */
}

Please note that the module map language is not guaranteed to work between major versions of Clang. Therefore, if the major version of Clang included in Xcode changes, you need to make sure that the behavior around here is what the developer intended.

The module map language is not currently guaranteed to be stable between major revisions of Clang.

Summary

I introduced how to use the C library in Swift by preparing a modulemap.

The modulemap may not work in one shot, so be prepared and prepare it as a set.

An example of module map is described in the reference material.

Reference material

Recommended Posts

Use C library with Swift using Clang Modules (modulemap)
Getting started with Swift / C bridges with porting Echo Server using libuv
Use cuda11.0 with pytorch using Docker
I tried using Realm with Swift UI
Call Java library from C with JNI
Display images with exact AutoLayout ratio using image loading library Nuke in Swift