ログ日記

作業ログと日記とメモ

CからHaskellを使う

C言語C++はどうなんだろう・・取り敢えず動くところまでやってみた。


昔作ったwiki http://www.n314.com/Haskell/wiki/ をCから呼び出してみる。

import CGI
import Qwiky
import Config

main = do cfg <- loadConfig "config.ini"
          runCGI $ quwiky cfg

Main.hs はこんな感じだったので

module QwikyCGI where

import CGI
import Qwiky
import Config

import Foreign.C.String

foreign export ccall hsOutput :: IO String

hsOutput = do cfg <- loadConfig "config.ini"
              ret <- runCGI $ quwiky cfg
              return $ newCString ret

main関数の名前を変えてCStringを返すように変更する。


そしてC。

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

#ifdef __GLASGOW_HASKELL__
#include "QwikyCGI_stub.h"
extern void __stginit_QwikyCGI(void);
#endif

int main(int argc, char *argv[])
{
    hs_init(&argc, &argv);

#ifdef __GLASGOW_HASKELL__
    hs_add_root(__stginit_QwikyCGI);
#endif

    printf("X-Powered-By: C_and_Haskell\r\n");
    printf("%s", hsOutput());

    hs_exit();
    return 0;
}

ここまではいいんだけど、コンパイルがなかなか通らなくて苦労した。


.hsファイルが10個ほどあるので、 --make をつけないと大変。だけどつけると .c の関係も見てしまってコンパイルが通らない。
それが通ってもネットワークやパーサコンビネータのところでエラーが出る。

最終的には

ghc -W --make -cpp -optl-static -fffi QwikyCGI.hs
ghc -W -fffi -o index.cgi -package parsec -package network *.o index.c

とすることによってコンパイルが通った。
ハマりどころその2、-packageでも苦労した。

> Unfortunately I get a host of undefined references to basically all the
> functions in matrixstack.dll and also some undefined references of the form
> Parsefile.o:ghc2996_0.hc:(.text+0x130): undefined reference to
> `TextziParserCombinatorsziParsecziError_show_closure'
> Parsefile.o:ghc2996_0.hc:(.text+0x220): undefined reference to
> `TextziParserCombinatorsziParsecziChar_spaces_closure'
> Parsefile.o:ghc2996_0.hc:(.text+0x24a): undefined reference to
> `TextziParserCombinatorsziParsecziChar_spaces_closure'
> Parsefile.o:ghc2996_0.hc:(.text+0x29c): undefined reference to
> `TextziParserCombinatorsziParsecziChar_spaces_closure'

Add

  • package parsec

to you ghc commandline. And similary for any other packages you used while
compiling.

http://archive.netbsd.se/?ml=haskell-cafe&a=2006-09&t=2582627

ファイル名を全部指定すると一度でコンパイル出来るけどそれはやめておいて、先に --make でコンパイルしてから C のオブジェクトファイルとリンクする。



単純にCのmainから呼んだだけなのでまだ意味はないけど、もう少し現実逃避。
いやー新しいことは楽しいね。気付いたら朝の8時になってたよ。


参考: http://d.hatena.ne.jp/m-a-o/20070211#p3