SwiftでUnsafePointer<T>などのポインタを扱う

この記事は[Swift Advent Calendar 2014](http://qiita.com/advent-calendar/2014/swift)の12日目の記事です。

Advent Calendarも折り返し地点目前です。
12月も既に12日となっており、年の瀬をひしひしと感じさせますね。

私感ですが、年を取るごとに一年がとても早く感じます。
先人が**「一年の体感日数は年齢の逆数となる」**という言葉も残していますしね。
（1以上の逆数をとっても値はそこまで変わらないというツッコミはしないでおきましょう）

----

さて、それではSwiftの話題へ移りましょう。

Swiftについて言語設計は良いのですが、まだまだXcodeのサポートとコンパイラがそこまでなため、一度は個人でアプリを作ったもののモチベーションがあがりません。
（あるコードを最適化すると無限ループする事も）

今回はコンパイラー・・の話ではなく、ポインタを使ってメモリに直接アクセスする話です。

## Swiftでポインタを使用する

### SwiftのC言語への互換性

まず、SwiftにはC言語と互換性のあるAPIが存在しています。
※詳しくはこちら→[Interacting with C APIs](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html)


例えば、iOS, Macのアプリケーションを作成してる途中に

```swift
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error) {
     println("Unresolved error \(error), \(error?.localizedDescription)")
}
return _fetchedResultsController!
```

と書いた覚えがあるはずです。（プロジェクトのCoreDataテンプレートにあります）

この`NSError?`で宣言された変数のアドレスを`performFetch`の引数へ渡しています。

`performFetch`の定義を見に行くと

```swift
func performFetch(error: NSErrorPointer) -> Bool
```

となっており、`NSErrorPointer`は下記のようにエイリアスされています。

```swift
typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>
```

ここにある`AutoreleasingUnsafeMutablePointer<T>`がC言語のポインタとして連携してくれます。

### `UnsafePointer<T>`などなど

本来、Swiftにはメモリへ直接アクセスすることはできません。

ですが、先に述べたC言語との互換APIにある`UnsafePointer<T>`などを利用し、それらを可能にしています。

先ほどから`UnsafePointer<T>`**など**と言っておりますが、他にも種類が公式のリファレンスに書いてあります。

----

For return types, variables, and arguments, the following mappings apply:

|C Syntax | Swift Syntax|
|:-----|:-----|
|`const Type *`|`UnsafePointer<Type>`|
|`Type *`|`UnsafeMutablePointer<Type>`|


For class types, the following mappings apply:

|C Syntax|Swift Syntax|
|:-----|:-----|
|`Type * const *`|`UnsafePointer<Type>`|
|`Type * __strong *`|`UnsafeMutablePointer<Type>`|
|`Type **`|`AutoreleasingUnsafeMutablePointer<Type>`|

----

上記の通り、ポインタの種類は

- Constant Pointers
- Mutable Pointers
- Autoreleasing Pointers

に分けられています。

特徴として

- C言語の`NULL`を表現するにはSwiftでは`nil`を使用
- 必要があれば`UnsafePointer<Type>`に変換されます

### 実装について

これらを実際に使ってみましょう。

今回はポインタの例として、swapByPointer関数を作って紹介します。（swap関数はポインタの例で頻出してますね。）

型は任意の型にしたいため、ジェネリクスを使います。

**swapByPointer関数**

```swift
func swapByPointer<T>(x: UnsafeMutablePointer<T>, y: UnsafeMutablePointer<T>) {
    let z: T = x.memory
    x.memory = y.memory
    y.memory = z
}
```

**呼び出し**

```swift
var a: Int = 10
var b: Int = 20

// a = 10, b = 20
println("a = \(a), b = \(b)")

// Swap
swapByPointer(&a, &b)

// a = 20, b = 10
println("a = \(a), b = \(b)")
```

このような感じです。

なんてことはない普通のswap関数を定義して、その引数にアドレスを渡しています。
関数の中でアドレスが指すメモリに直接代入を行っています。

#### In-Out （おまけ）

「いやいや、そんなの`inout`使ったほうがシンプルでしょ？」のツッコミはあるかと思います。

今回は**ポインタ**を明示的に使いたいので、`inout`は使いません。

「`inout`ってなに？」という方は下記のコードを読んでください。

**swapByInout関数（inout使用版）**

```swift
func swapByInout<T>(inout x: T, inout y: T) {
    let z: T = x
    x = y
    y = z
}
```

**呼び出し**

```swift
var a: Int = 10
var b: Int = 20

// a = 10, b = 20
println("a = \(a), b = \(b)")

// Swap
swapByInout(&a, &b)

// a = 20, b = 10
println("a = \(a), b = \(b)")
```

### メモリ管理

さっきのは既に確保している変数のアドレスから参照していましたが、C言語に慣れている人なら「**memory alloc**は！？」となるでしょう。

もちろんあります。

**alloc**

```swift
// Use UnsafeMutablePointer<T>
typealias IntPointer = UnsafeMutablePointer<Int>
// C Language:
//  typedef int *IntPointer;

var a_ptr = IntPointer.alloc(1)
// C Language:
//  int *a_ptr = (int *)malloc(1 * sizeof(int));
//  IntPointer a_ptr = (IntPointer)malloc(1 * sizeof(int));
//   or
//  int *a_ptr = (int *)calloc(1, sizeof(int));
var b_ptr = IntPointer.alloc(1)

a_ptr.memory = a
// C Language:
//  *a_ptr = a;
b_ptr.memory = b

// a_ptr.memory = 10, b_ptr.memory = 20
println("a_ptr.memory = \(a_ptr.memory), b_ptr.memory = \(b_ptr.memory)")

// Swap
swapByPointer(a_ptr, b_ptr)

// a_ptr.memory = 20, b_ptr.memory = 10
println("a_ptr.memory = \(a_ptr.memory), b_ptr.memory = \(b_ptr.memory)")

// Destroy
a_ptr.dealloc(1)
// C Language:
//  free(a_ptr);
b_ptr.dealloc(1)
```

コメントとしてC言語のときの状況も記しておきました。

解説が必要そうなコードは `alloc`, `dealloc`, `memory` の3つですかね。

#### var p = UnsafeMutablePointer<T>.alloc(num)

C言語では

```c
Type *p = (Type *)malloc(num * sizeof(Type));
// or
Type *p = (Type *)calloc(num, sizeof(Type));
```

となります。

必要分のメモリサイズを確保するための、宣言した型の個数を`num`に指定します。

#### p.dealloc(num)

C言語では

```c
free(p);
```

解放しています。

#### p.memory

C言語では

```c
*p
```

です。アドレスにある値を参照するために使用します。

----

大体、この程度を知っていればC言語のような考えでSwiftを組むことができます。

### おわりに

今回のコードをGistにあげているので、よければ参照してください。

https://gist.github.com/kaneshin/564fc0780e0d1c9cac7d

また、ポインタの話がでたなら**「関数ポインタは？」**という方が出てくるはずです。

もちろん、関数ポインタを扱うための互換APIも用意されています。
それは誰かが知りたいというか、この記事の**ストック数が100**くらいになったら紹介するとしましょう。

こんな誰得な情報でしたが、Swiftでポインタを扱う日本語の記事は無いと思うので、もしよければ触ってみてください。

※SwiftではStructを恰もポインタらしく使ってるだけです。