BACK
Swift & C

Swift & C

K

Kcat

2018年1月5日 15:105 min read

因为 Swift 是建立在 LLVM 之上的,所以 Swift 是支持与 C 交互的。但是在 Swift 中,让其与 C 混编是一件说起来有点麻烦又不太麻烦的事儿,麻烦就是要实现混编可能需要一些零碎的步骤,不麻烦就是 Swift 也提供了和 C 对应的等价类型来进行转换使用

让 Swift 可调用 C

创建 Module Map 文件

Swift 是建立在 LLVM1 之上的,并且两者都是 Chris Lattner 的杰作,所以当然也就支持 LLVM 的 Module2 模块,而我们需要使用的是此模块中的 Module Map Language3

Module Map Language 是用来描述模块头文件逻辑的,而我们需要为模块创建一个名称为 module.modulemap 的文件,并且文件需要使用 Module Map Language 来描述模块逻辑,以便 Swift 导入

首先我们拥有这样一个结构的目录:

Project structure

我们拥有两个 C 文件名为 hello.chello.h,并且 hello.c 只有一个函数 hello

#include "hello.h"

void hello() {
    printf("Hello");
}

我们现在目前是无法进行调用的,这个时候需要在 Hello 目录下创建一个文件名为 module.modulemap 的 Module Map 文件,并且内容为:

module Hello {
    header "hello.h"
    export *
}

这段表示我们创建了一个名为 Hello 的模块,并且描述了 hello.h 为头文件

导入 Module Map 文件

创建好了 Module Map 文件之后,我们需要让编译器能够找到 Module Map 文件,这样才可以进行调用

我们进入 Build Settings 中,找到 Swift Compiler - Search Paths 部分下的 Import Paths,把 Module Map 文件的路径添加上:

Import Paths

调用 C 函数

这个时候,便可以在任意的 Swift 文件中导入 Hello 模块并使用 C 函数:

import Hello

func printHello() {
    hello()
}

Swift & C 的交互

Swift & C 的等价类型表

在 Apple 的官方文档4中,就详细列出了两者之间的等价类型:

CSwiftTypealias
boolCBoolBool
char, signed charCCharInt8
unsigned charCUnsignedCharUInt8
shortCShortInt16
unsigned shortCUnsignedShortUInt16
intCIntInt32
unsigned intCUnsignedIntUInt32
longCLongInt
unsigned longCUnsignedLongUInt
long longCLongLongInt64
unsigned long longCUnsignedLongLongUInt64
wchar_tCWideCharUnicodeScalar
char16_tCChar16UInt16
char32_tCChar32UnicodeScalar
floatCFloatFloat
doubleCDoubleDouble

Footnotes

  1. LLVM

  2. LLVM Modules

  3. Module Map Language

  4. Interacting with C APIs

— THE END —