Skip to content

Commit

Permalink
Upgrading to Swift 4.
Browse files Browse the repository at this point in the history
  • Loading branch information
RockfordWei committed Jan 23, 2018
1 parent 5062364 commit 3f48123
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 108 deletions.
26 changes: 25 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "CSwift"
name: "CSwift",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "CSwift",
type: .`dynamic`,
targets: ["CSwift"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "CSwift",
dependencies: []),
.testTarget(
name: "CSwiftTests",
dependencies: ["CSwift"]),
]
)
100 changes: 43 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Rockford Wei,2017-01-17

Last update: 2018-01-23

This project demonstrates how to call a customized C library in your swift project.
You can clone it from github, or follow the instruction below to generate it step by step.

Expand All @@ -14,7 +16,7 @@ There are two C files: CSwift.c and CSwift.h. The objective is to build a CSwift

## Quick Start

Please compile this project with Swift 3.0 toolchain.
Please compile this project with Swift 4.0.3 toolchain.

### Build & Test

Expand All @@ -36,87 +38,60 @@ However, even without the sources above, you can still start everything from bla
Assume the objective library is still CSwift, then find an empty folder and try these commands in a terminal:

```
$ mkdir CSwift
$ cd CSwift
$ swift package init --type=system-module
$ mkdir CSwift
$ cd CSwift
$ swift package init
$ mv Tests ..
$ mkdir include
$ mv ../module.modulemap inlcude/
$ rm Package.swift
$ rm -rf Sources
$ echo > CSwift.c
$ echo > include/CSwift.h
$ cd ..
```

You may notice that the above commands make a second CSwift folder inside the first one, but with different `swift package` commmand line.
The first `swift package` is to create a blank swift project and will build as an system module; The second one, however, is just to create a common swift library.
The purpose of such a trick is to create testing scripts for system module.

Besides, it also creates an `include` folder under the second CSwift directory, with two blank source file place holder `CSwift.c` and `CSwift.h`.

### Module Map

Now it is time to modify the module map file, check this out:

``` swift
module CSwift [system] {
header "CSwift.h"
link "CSwift"
export *
}
mkdir CSwift && cd CSwift && swift package init
mkdir Sources/CSwift/include && rm Sources/CSwift/CSwift.swift
```

### C Code
The above commands will set up the empty project template

Then you can customize the C code as demo below:
### C Header File

#### CSwift/CSwift/include/CSwift.h
Now edit the header file `Sources/CSwift/include/Swift.h`:

``` c
extern int c_add(int, int);
#define C_TEN 10
```
#### CSwift/CSwift/CSwift.c
### C Source
Finishing the implementation of the C body `Sources/CSwift/CSwift.c`:
``` c
#include "include/CSwift.h"
int c_add(int a, int b) { return a + b ; }
```

Up to now, C api is ready to call. So far so good.
### Module Map

Next, we will setup an umbrella file for swift:
`Sources/CSwift/include/module.modulemap`

``` swift
module CSwift [system] {
header "CSwift.h"
export *
}
```

### Call C API in Swift

The following code is a good example to show how to call your C api statically, as `Tests/CSwiftTests/CSwiftTests.swift`:
Now let's check if the library works by editing a test script:
`Tests/CSwiftTests/CSwiftTests.swift`

``` swift

import XCTest
@testable import CSwift

class CSwiftTests: XCTestCase {
func testExample() {
// Test call "x + y" from your C library
let three = c_add(1, 2)
XCTAssertEqual(three, 3)

// Test macro exports
XCTAssertEqual(C_TEN, 10)
}


static var allTests : [(String, (CSwiftTests) -> () throws -> Void)] {
return [
("testExample", testExample),
]
}
func testExample() {
let three = c_add(1, 2)
XCTAssertEqual(three, 3)
XCTAssertEqual(C_TEN, 10)
}
static var allTests : [(String, (CSwiftTests) -> () throws -> Void)] {
return [ ("testExample", testExample) ]
}
}

```

### Test
Expand All @@ -137,6 +112,17 @@ This project also makes an example for swift script, and even more, introduces h

### Dynamic Link Library

The default linking object of Swift 4 is static, so it needs a bit modification to turn it into a dynamic one.

To do this, edit the Package.swift file, and add a line:

``` swift
.library(
name: "CSwift",
type: .`dynamic`, // <------------ Insert the dynamic type right here!
targets: ["CSwift"]),
```

Please check a swift script `dll.swift.script`, actually it is a common swift with no difference to any other swift sources:

``` swift
Expand Down
93 changes: 44 additions & 49 deletions README.zh_CN.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Swift 调用 C 语言自建函数库 及 Swift 脚本和动态链接库的使用方法 [English](README.md)
# Swift 调用 C 语言自建函数库 及 Swift 脚本和动态链接库的使用方法

Rockford Wei,2017-01-17

最近更新:2018-01-23

本程序示范了如何用Swift调用自定义C语言模块的方法。您可以直接下载本程序,或者按照以下教程逐步完成。
此外,示范程序还展示了如何使用 Swift 作为脚本运行,并且在脚本中调用C语言的动态链接库,使得服务器端Swift 开发实现热补丁。

Expand All @@ -11,7 +13,7 @@ Rockford Wei,2017-01-17

## 快速上手

本程序需要Swift 3.0以上版本
本程序需要Swift 4.0.3 以上版本

### 下载、编译和测试

Expand All @@ -32,55 +34,41 @@ $ swift test
仍然假定函数库名称为CSwift。首先找一个空白目录,然后执行:

```
$ mkdir CSwift
$ cd CSwift
$ swift package init --type=system-module
$ mkdir CSwift
$ cd CSwift
$ swift package init
$ mv Tests ..
$ mkdir include
$ mv ../module.modulemap include/
$ rm Package.swift
$ rm -rf Sources
$ echo > CSwift.c
$ echo > include/CSwift.h
$ cd ..
```

细心的读者会发现,上面的bash 命令行在CSwift 文件夹下面建立了第二个CSwift文件夹,但是使用了不同的`swift package`了命令。第一个命令是“创建swift空白项目,而且项目类型是系统模块”;而第二个命令是“创建swift 空白项目,项目类型是函数库”。这种做法主要是为了能够在同一个项目中用Swift去测试C语言的模块。其次,在第二个CSwift 子目录下,还建立了一个include 文件夹,并分别建立了两个空白源程序文件 CSwift.c 和 CSwift.h

### Module Map

下一步是修理一下目标的模块映射表。请把module.modulemap修改为如下程序:

``` swift
module CSwift [system] {
header "CSwift.h"
link "CSwift"
export *
}
mkdir CSwift && cd CSwift && swift package init
mkdir Sources/CSwift/include && rm Sources/CSwift/CSwift.swift
```

### C模块编程
上述命令能够新建一个空白的函数库模板

好了,现在请编辑刚才在第二个CSwift文件夹下面的建立两个C语言文件:CSwift.c和CSwift.h,内容如下:
### C 函数头文件

#### CSwift/CSwift/include/CSwift.h
现在编辑头文件 `Sources/CSwift/include/Swift.h`:

``` c
extern int c_add(int, int);
#define C_TEN 10
```
#### CSwift/CSwift/CSwift.c
### C 函数体文件
然后通过修改文件 `Sources/CSwift/CSwift.c`完成函数实现:
``` c
#include "include/CSwift.h"
int c_add(int a, int b) { return a + b ; }
```

到此为止,C语言函数库就应该准备好了。
### 模块映射

下一步为Swift 语言构造一个映射模块文件:
`Sources/CSwift/include/module.modulemap`

``` swift
module CSwift [system] {
header "CSwift.h"
export *
}
```

### Swift 程序调用

Expand All @@ -92,20 +80,17 @@ import XCTest
@testable import CSwift

class CSwiftTests: XCTestCase {
func testExample() {
// 测试调用 C 函数
let three = c_add(1, 2)
XCTAssertEqual(three, 3)
// 测试调用 C 语言的符号
XCTAssertEqual(C_TEN, 10)
}


static var allTests : [(String, (CSwiftTests) -> () throws -> Void)] {
return [
("testExample", testExample),
]
}
func testExample() {
// 测试调用 C 函数
let three = c_add(1, 2)
XCTAssertEqual(three, 3)
// 测试调用 C 语言的符号
XCTAssertEqual(C_TEN, 10)
}

static var allTests : [(String, (CSwiftTests) -> () throws -> Void)] {
return [ ("testExample", testExample)]
}
}

```
Expand All @@ -128,6 +113,16 @@ $ swift test

### 动态链接库

默认的Swift 4为静态编译,因此如果希望使用动态链接,则需要做一个调整。
请打开Package.swift文件增加下一行:

``` swift
.library(
name: "CSwift",
type: .`dynamic`, // <------------ 在这里增加新的一行
targets: ["CSwift"]),
```

本项目附带了一个特殊脚本dll.swift.script,内容为一个普通Swift 源程序:

``` swift
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
module CSwift [system] {
header "CSwift.h"
link "CSwift"
export *
}

0 comments on commit 3f48123

Please sign in to comment.