書いて覚えるSwift入門

第6回 サードパーティC/Objective-Cプロジェクトの利用

この記事を読むのに必要な時間:およそ 4 分

前回前々回ではそれぞれC(libc)とObjective-C(Foundation)をSwiftから活用してみましたが,どちらもiOS/OS X標準のAPIへのアクセスでした。今回はサードパーティのC/Objective-Cプロジェクトを,Swiftから活用する方法を実例をもとに見ていきます。

swift-gmpint

ご存じのとおり,Swiftにおける整数=Intは,C/Objective-C/C++のint同様,1ワード。64bitプラットフォームなら64bit,32bitプラットフォームなら32bitです。しかしRubyやPythonやHaskellなど,昨今の言語では組み込みの整数を任意精度にする事例が増えています。Swiftでも任意精度の整数を扱えるようにしたいというのは自然の欲求というものでしょう。任意精度整数が組み込みでない言語でその欲求を叶える方法としては,次の2通りが考えられます。

  • A.100%自分で実装
  • B.既存のライブラリを活用

たとえばJavaScriptでは事実上A.の方法しか採れませんが,SwiftならプランB.があります。Mathematicaでも採用されている定番の任意精度整数ライブラリ,GMPを,そのままSwiftから使えるようにしてしまえばいいのです。

そんなわけで作ったのがswift-gmpintです。MacPortsでインストールしたGMPを,Swiftから使えるようにします。

Homebrew派の皆さん,ごめんなさい。ただし未確認ではありますが,本記事中の/opt/local/usr/localにすればもしかして動くかもしれません。fork welcome!

Quick Start

前口上は抜きにして早速試してみたいという読者は,次のようにしてください。

  • ① MacPortsをインストール

  • ② MacPortsからGMPをインストール

    % sudo port install gmp
    
  • ③ GitHubからswift-gmpintをインストール

    % git clone https://github.com/dankogai/swift-ュgmpint.git
    
  • ④ Xcodeでプロジェクトをオープン

    % open swift-gmpint/gmpint.xcodeproj
    
  • ⑤ プロジェクトを実行

標準出力を確認してみてください。2**1024が179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216であることなどが確認できます。さらにmain.swiftをあれこれ書き換えてみて,任意精度整数演算を楽しんでみてください。

普通のプロジェクトとの違い

それでは,実際のプロジェクトをみてみましょう。まずはプロジェクトファイル図1から。

図1 通常のSwiftプロジェクトとの違い

図1 通常のSwiftプロジェクトとの違い

通常のプロジェクトとの一番の違いは,Cフラグとリンクオプション。-lgmp-I/opt/local/include -L/opt/local/libが追加してあります。ほかは通常のSwiftプロジェクトと変わりません。

次にプロジェクト中のファイルをみてみましょう。

  • main.swift
  • mpz.swift
  • gmp-int-Bridging-Header.h
  • mpz.c

特徴的なのが,mpz.cgmpint-Bridging-Header.h[Using Swift with Cocoa and Objective-C]に出てくる三角形の上2つがこれに相当します図2)。前々回と前回のプロジェクトではXcode組み込みのファウンデーションを利用していたためこれらは不要でしたが,今回はGMPというサードパーティライブラリを使うため必要となります。

ちなみにgmp-int-Bridging-Header.hは,Xcodeにひな型を生成させることもできますが,* プロジェクト名*-Bridging-Header.hという名前をつけてプロジェクトに手で追加してもOKです図3)。

図3 Bridging-Header.hの追加

図3 Bridging-Header.hの追加

それでは,gmp-int-Bridging-Header.hを見てみましょうリスト1)。

リスト1 gmp-int-Bridging-Header.h

#include <gmp.h>
void gmpint_seti(mpz_t *op, long i);
void gmpint_sets(mpz_t *op, const char *str, int base);
void gmpint_unset(mpz_t *op);
size_t gmpint_strlen(mpz_t *op, int base);
char *gmpint2str(mpz_t *op, int base);
int gmpint_fits_int(mpz_t *op);
long gmpint2int(mpz_t *op);
int gmpint_cmp(mpz_t *op, mpz_t *op2);
void gmpint_negz(mpz_t *rop, mpz_t *op);
void gmpint_absz(mpz_t *rop, mpz_t *op);
void gmpint_lshift(mpz_t *rop, mpz_t *op, mp_bitcnt_t bits);
void gmpint_rshift(mpz_t *rop, mpz_t *op, mp_bitcnt_t bits);
void gmpint_addz(mpz_t *rop, mpz_t *op, mpz_t *op2);
void gmpint_subz(mpz_t *rop, mpz_t *op, mpz_t *op2);
void gmpint_mulz(mpz_t *rop, mpz_t *op, mpz_t *op2);
void gmpint_divmodz(mpz_t *r, mpz_t *q, mpz_t *op, mpz_t *op2);
void gmpint_powui(mpz_t *rop, mpz_t *op, unsigned long exp);
void gmpint_powmodz(mpz_t *rop, mpz_t *op, mpz_t *exp, mpz_t *mod);

これらの関数名が,Swiftでそのまま使えます。ただしそのまま使えるのは関数名までで,型の名前は読み替えが必要になります。たとえばCintはSwift上でInt32になりますし,char*UnsafePointer<Int8>になります。Cの型名とSwiftの型名の対応表は[Using Swift withCocoa and Objective-C]にも載っていますが,実際にはXcodeのコード補完でいつでも確認できるのでそれほど気にする必要はないでしょう。IDE万歳といったところです。

著者プロフィール

小飼弾(こがいだん)

1969年生まれ,東京都出身。元ライブドア取締役の肩書きよりも,最近はPokemon GOのガチトレーナーのほうが有名になりつつある……かもしれない永遠のエンジニアオヤジ。

活躍の場はIT業界だけでなく,サブカルからアカデミックまで多方面にわたり,ネットからの情報発信は気の向くまま毎日毎秒! https://twitter.com/dankogai,ニコニコチャンネルは,http://ch.nicovideo.jp/dankogai,blogはhttp://blog.livedoor.jp/dankogai/

当社刊行書籍は『小飼弾のアルファギークに逢ってきた』『小飼弾のコードなエッセイ』など。他にも著書多数。

コメント

コメントの記入