【问题标题】:Building a haskell interpreter (hint) as dynamic library, useable from C++: Missing Interpreter.dyn_hi将 haskell 解释器(提示)构建为动态库,可在 C++ 中使用:Missing Interpreter.dyn_hi
【发布时间】:2012-01-31 20:41:21
【问题描述】:

我想创建一个可以在 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 文件。

【问题讨论】:

    标签: c++ haskell ghc ffi hint


    【解决方案1】:

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

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

    cabal install --reinstall world

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

    【讨论】:

    • 这不会有好的结局,至少它不适合我。在他完成重新编译所有库之后,他会遇到 GHC 附带的库没有使用 dyn 或 -fPIC 编译的问题,因此他必须获取 GHC 源并重新编译和编辑 makefile。然后当他完成时,他仍然会得到一个错误,即 libFFI 没有使用 -fPIC 编译,显然,它没有继承 build.mk 的设置,所以你编辑它并重新编译,它仍然会给你一个错误。这就是我被困住的地方stackoverflow.com/questions/7652799/…
    • 啊,可惜了。我不记得确切的时间,也不知道发生了什么变化,但不久前 libFFI 的处理方式发生了变化,也许这将使其成为可能。你试过 HEAD 吗?
    • 我用的是7.0.3的src,我试试HEAD,看看能不能用。
    猜你喜欢
    • 2012-01-31
    • 2014-05-18
    • 2012-01-28
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多