Linux で C++ から使用できる Haskell インタープリターを作成したいと考えています。
Haskell でインタープリターを実装し、FFI 経由で関数を C++ にエクスポートするファイル FFIInterpreter.hs があります。
module FFIInterpreter where
import Language.Haskell.Interpreter
import Data.IORef
import Foreign.StablePtr
import Foreign.C.Types
import Foreign.C.String
import Control.Monad
import Foreign.Marshal.Alloc
type Session = Interpreter ()
type Context = StablePtr (IORef Session)
foreign export ccall createContext :: CString -> IO Context
createContext :: CString -> IO Context
createContext name = join ((liftM doCreateContext) (peekCString name))
where
doCreateContext :: ModuleName -> IO Context
doCreateContext name
= do let session = newModule name
_ <- runInterpreter session
liftIO $ newStablePtr =<< newIORef session
newModule :: ModuleName -> Session
newModule name = loadModules [name] >> setTopLevelModules [name]
foreign export ccall freeContext :: Context -> IO ()
freeContext :: Context -> IO ()
freeContext = freeStablePtr
foreign export ccall runExpr :: Context -> CString -> IO CString
runExpr :: Context -> CString -> IO CString
runExpr env input = join ((liftM newCString) (join (((liftM liftM) doRunExpr) env (peekCString input))))
where
doRunExpr :: Context -> String -> IO String
doRunExpr env input
= do env_value <- deRefStablePtr env
tcs_value <- readIORef env_value
result <- runInterpreter (tcs_value >> eval input)
return $ either show id result
foreign export ccall freeString :: CString -> IO ()
freeString :: CString -> IO ()
freeString = Foreign.Marshal.Alloc.free
プロジェクト全体を ghc でコンパイルすると、すべて正常に動作します。次のコマンドを使用します。
ghc -no-hs-main FFIInterpreter.hs main.cpp -lstdc++
しかし、haskell モジュールは C++ プロジェクトのほんの一部にすぎず、プロジェクト全体を ghc に依存させたくありません。
そこで、ghc で動的ライブラリを構築し、g++ を使用してプロジェクトにリンクしたいと考えています。
$ ghc -shared -fPIC FFIInterpreter.hs module_init.c -lstdc++
[1 of 1] Compiling FFIInterpreter ( FFIInterpreter.hs, FFIInterpreter.o )
Linking a.out ...
/usr/bin/ld: /usr/lib/haskell-packages/ghc/lib/hint-0.3.3.2/ghc-7.0.3/libHShint-0.3.3.2.a(Interpreter.o): relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/lib/haskell-packages/ghc/lib/hint-0.3.3.2/ghc-7.0.3/libHShint-0.3.3.2.a: could not read symbols: Bad value
collect2: ld gab 1 als Ende-Status zurück
-dynamic キーワードを追加しましたが、これも機能しません。
$ ghc -dynamic -shared -fPIC FFIInterpreter.hs librarymain.cpp -lstdc++
FFIInterpreter.hs:3:8:
Could not find module `Language.Haskell.Interpreter':
Perhaps you haven't installed the "dyn" libraries for package `hint-0.3.3.2'?
Use -v to see a list of the files searched for.
システムで Interpreter.dyn_hi を検索しましたが、見つかりませんでした。それを取得する方法はありますか?ヒントを手動でインストールしようとしましたが、これも Interpreter.dyn_hi ファイルを配信しません。