3

我想创建一个可以从 Linux 上的 C++ 使用的 haskell 解释器。

我有一个文件 FFIInterpreter.hs,它在 haskell 中实现解释器并通过 FFI 将函数导出到 C++。

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 文件。

4

1 回答 1

3

您必须使用标志(使用 cabal-install)安装库(以及它所依赖的所有内容--enable-shared)才能获取.dyn_hi.dyn_o文件。您可以考虑在~/.cabal/config文件中设置该选项。

也许最简单的方法是取消注释中的shared: XXX~/.cabal/config,将选项设置为Trueand

阴谋集团安装--重新安装世界

为了安全起见,请先使用选项运行它以及--dry-run早发现问题。如果--dry-run输出看起来合理,请继续重新安装 - 不过这需要一段时间。

于 2012-01-02T15:19:04.240 回答