はじめに
去る2015年12月3日、Swift がオープンソース化され、Linux 版も公開されました。すばらしい。
Swift.org - Welcome to Swift.org
ちょっと無理矢理にですが、Ruby から呼んでみました。
注意: 2015年12月現在、Swift のコードを Objective-C 以外の言語から呼ぶ方法は公式にはアナウンスされていません。
本記事は、独自に試した結果を書いています。
環境
- Ubuntu 14.04 LTS(Trusty Tahr) 64bit
$ ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
$ swiftc -v
Swift version 2.2-dev (LLVM 46be9ff861, Clang 4deb154edc, Swift 778f82939c)
Target: x86_64-unknown-linux-gnu
Swift、はやい
最初にRubyとSwiftの計算速度を比べるため、フィボナッチ数を単純に計算するやつをそれぞれ書きました。
def fib(n)
return n if n <= 1
fib(n - 1) + fib(n - 2)
end
puts fib(40)
func fib(n: Int) -> Int {
if n <= 1 {
return n
}
return fib(n - 1) + fib(n - 2)
}
print(fib(40))
実行結果は以下です。
$ time ruby fib.rb
102334155
real 0m22.581s
user 0m22.558s
sys 0m0.041s
$ time swift fib.swift
102334155
real 0m1.077s
user 0m1.040s
sys 0m0.029s
$ swiftc -O fib.swift
$ time ./fib
102334155
real 0m0.374s
user 0m0.374s
sys 0m0.000s
Swift はいい感じにはやいです。
Swift を共有ライブラリにする
print
文を取り除き、fib
関数を public
宣言します。
public func fib(n: UInt) -> UInt {
if n <= 1 {
return n
}
return fib(n - 1) + fib(n - 2)
}
Linux 上では現状、次のようにして Swift の共有ライブラリを作れるようです。 (注: 今後変わる可能性はあります)
$ swiftc -emit-library -emit-object -module-name fib -O fib.swift
$ clang -shared -o libfib.so fib.o
生成された共有ライブラリの中身を見てみます。
$ nm -D libfib.so
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
0000000000000680 T _TF3fib3fibFSuSu
0000000000201038 B __bss_start
w __cxa_finalize
w __gmon_start__
0000000000201038 D _edata
0000000000201040 B _end
00000000000006bc T _fini
0000000000000528 T _init
fib
関数の名前はマングリングされ _TF3fib3fibFSuSu
というシンボルになっています。
なんとなく呼べそうです。
Ruby から Swift の関数を呼ぶ
さきほどの共有ライブラリを ffi
を用いて呼ぶわけですが、今の所、マングリングされたシンボル名を使って呼んでやる必要があります。
require "ffi"
module Fib
extend FFI::Library
ffi_lib "libfib.so"
attach_function :_TF3fib3fibFSuSu, [:uint], :uint
end
puts Fib._TF3fib3fibFSuSu(40)
Ruby meets Swift
$ time LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ruby swift-fib.rb
102334155
real 0m1.044s
user 0m1.009s
sys 0m0.037s
無事に呼べました。そして、はやいですね。
どの言語も仲良く平和にやっていきましょう。
補足
冒頭にも書きましたが、この記事で示した Swift の共有ライブラリを外部から呼ぶ方法は、公式のものではありません。
したがって、何らの保証もできません。良い子はマネしないでね!
ただ、Swift は元々 Apple の Objective-C1 との相互運用を考慮して設計されていることや、Swift 3.0 で ABI の安定化が図られるという話があり、Objective-C 以外との相互運用をするための下地は整ってきていると思います。
いずれちゃんとした形で Objective-C 以外との相互運用が実現されるだろう、と予想しています。
今後の Swift の発展が楽しみです。
参考
-
Objective-C 自体 C との相互運用性が考慮されている ↩