Archive for 12月, 2015

calling Haskell from Swift / Linux

土曜日, 12月 26th, 2015

今月Swiftがオープンソースとして公開されました。何か試したかったのでC言語とのリンクをと思ったのですが、少し踏み込んでHaskellにしてみました。

環境: swift-2.2-SNAPSHOT-2015-12-22-a-ubuntu15.10.tar.gz / Ubuntu 15.10

Swiftインストール:
https://swift.org/download/#latest-development-snapshots
からダウンロードした上記ファイルを解凍して、usr/binにパスを通します。
usr/lib/swift/linuxにある、libswiftCore.soをLinuxの/usr/local/libにコピーします。
とりあえず簡単なテストをするだけなので、これだけにしました。

export PATH:~/swift/usr/bin
sudo cp libswiftCore.so /usr/local/lib
sudo ldconfig

Haskellインストール:

sudo apt-get install ghc

fib.hs

module Fib where
import Foreign.C.Types

fibonacci :: Int -> Int
fibonacci n = fibs !! n
    where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral

foreign export ccall fibonacci_hs :: CInt -> CInt

参考: https://wiki.haskell.org/Calling_Haskell_from_C
このコードをそのまま使い、Swiftから呼び出してみます。

fibsw.swift

import Foundation

hs_start()

var a: CInt = 12
let fb = fibonacci_hs(a)
print("fibonacci \(a) : \(fb)")

hs_end()

なんとダイレクトで呼び出せてしまいます。しかし、初期化処理とか必要になってくるので、Cのグルーコードを用意します。

fibc.h

#include "fib_stub.h"

int hs_start();
int hs_end();

fibc.c

#include <stdio.h>
#include "fibc.h"

int hs_start()
{
   int argc = 2;
   char *argv[] = {"+RTS", "-A32m", NULL};
   char **pargv = argv;

   hs_init(&argc, &pargv);
   return 0;
}
int hs_end()
{
        hs_exit();
        return 0;
}

fib_stub.hは、Haskellコンパイル時に自動生成されます。

#include "HsFFI.h"
#ifdef __cplusplus
extern "C" {
#endif
extern HsInt32 fibonacci_hs(HsInt32 a1);
#ifdef __cplusplus
}
#endif

ビルド:

ghc -c -O fib.hs
cc -c -o fibc.o fibc.c -I/usr/lib/ghc/include
swiftc -c -o fibsw.o fibsw.swift -import-objc-header fibc.h -I/usr/lib/ghc/include
ghc –make -no-hs-main fibsw.o fibc.o fib.o -o fibsw -lswiftCore

実行結果:
SwiftCallHaskell01
SwiftがLinuxで手軽に使えると、サーバ、クライアントともSwiftで開発ができるのでいろいろと便利かもしれません。
Perfect.orgなども要注目ですね。