Tech Blog

グローバルな家族アプリFammを運営するTimers inc (タイマーズ) の公式Tech Blogです。弊社のエンジニアリングを支える記事を随時公開。エンジニア絶賛採用中!→ https://timers-inc.com/engineering

SwiftでC言語のライブラリを利用する

お久しぶりです。iOSエンジニアのかっくん(@fromkk)です。

iOSアプリなんかを作っている時に、SwiftからC言語のライブラリを利用したいなって思う事はないですか?
Foundationから直接呼べる物も結構ありますがインポートが必要なものを利用するのってあまり知られて無い様な気がするので備忘録として残しておきたいと思います。

同じようなテーマで検索するとたくさん出てきますが大抵が UnsafeMutablePointer<T> 等の使い方に寄っているかと思うのでその辺りの説明は詳しい方にお任せます(逃)
実用的な方がいいと思いますのでライブラリをインポートしないでも使える utsname とライブラリのインポートが必要な CommonCrypto で実際のコードを見ながら説明します。


ライブラリをインポートしないでも利用出来る utsname

実際にiPhoneのモデルが取得したくなったので色々調べていたら utsnamemachine を利用すれば出来る事が分かったので利用してみました。

var info: utsname = utsname()
uname(&info)
let mirror: Mirror = Mirror(reflecting: info.machine)
var machine: String = ""
for child in mirror.children {
    if let value = child.value as? Int8 where value != 0 {
        machine.append(UnicodeScalar(UInt8(value)))
    }
}
print(machine) //iPhone7,1

Swiftではあまり馴染みの無い参照渡しやリフレクションが散見されますね。

インポートが必要な CommonCrypto

サービスで使っている認証システムを利用する際にハッシュ化が必要でした。
Objective-Cだったら #import <CommonCrypto/CommonCrypto.h> で利用出来たんですがSwiftの場合は少々ややこしいです。

  • プロジェクト配下で CommonCrypto フォルダを作成
  • 作成したフォルダの中に module.modulemap というファイルを作成して下記の内容で保存する
module CommonCrypto {
    header "/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}
  • Project -> Build Setting -> Swift Compilier - Search Paths -> Import Paths に作成したフォルダのパスを追加する(例: ${SRCROOT}/CommonCrypto

これで準備完了です。以下に sha256 のサンプルを記載しておきます。

import CommonCrypto

func sha256(data: NSData) -> String {
    let digestLen: Int = Int(CC_SHA256_DIGEST_LENGTH)
    let buffer: UnsafeMutablePointer<CUnsignedChar> = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
    CC_SHA256(data.bytes, CUnsignedInt(data.length), buffer)
    var sha256: String = ""
    for i in 0..<digestLen {
        sha256 = sha256.stringByAppendingFormat("%02x", buffer[i])
    }
    buffer.dealloc(digestLen)
    return sha256
}

いずれにしても通常のSwiftのコードではなかなか見ないコードが多いですし毎回記述するのは面倒臭いですよね。
ということで上記の utsnameCommonCrypto をラッピングしたライブラリを作成しました。

Utsname

fromkk/Utsname は上記の utsname を簡単に取得出来る様にする為のラッパーです。 Cartfilegithub "fromkk/Utsname" を追加して、 carthage update を実行してProjectの設定をすれば利用出来ます。(詳しくはCarthageを参照)

import Utsname

let info: Utsname = Utsname()
print(info.machine) //iPhone7,1

上記の様に簡単に utsname の値が取得出来ます。

HashKit

fromkk/HashKit は上記の CommonCrypto を簡単に利用出来る様にする為のラッパーです。 Cartfilegithub "fromkk/HashKit" を追加して、 carthage update を実行してProjectの設定をすれば利用出来ます。(詳しくはCarthageを参照)

import HashKit

let sha256: String = ".........".sha256()

上記の様に簡単にCommonCryptoのハッシュ化が利用出来ます。
もちろん md5sha1 等のよく利用するものや、 hmac も利用出来る様にしています。

詳しくはそれぞれのREADMEをご覧下さい! また気付いた点があればissueにご報告頂ければと思います。

Update 2016/08/30

それぞれのリポジトリswift-2.3 ブランチと swift-3 ブランチを作成しました。
Xcode 8でも安心して利用出来るかと思いますのでお試し頂ければと思います。


子育て家族アプリFammカップル専用アプリPairyを運営する Timers inc. では、現在エンジニアを積極採用中!急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP : http://timers-inc.com/engineerings

Timersでは各職種を積極採用中!

急成長スタートアップで、最高のものづくりをしよう。

募集の詳細をみる