Haskell 使用FFI声明时GHCi运行时链接器问题

Haskell 使用FFI声明时GHCi运行时链接器问题,haskell,linker,ffi,ghci,Haskell,Linker,Ffi,Ghci,我对Haskell中的FFI和GHC的交互模式有疑问 考虑FFISo.hs: {-# LANGUAGE OverloadedStrings #-} module Main where import qualified Data.ByteString.Char8 as B import FFIFun.Foo main :: IO () main = do B.putStrLn "main" callMeFromC callMeFromHaskell return () {-

我对Haskell中的FFI和GHC的交互模式有疑问

考虑
FFISo.hs

{-# LANGUAGE OverloadedStrings #-}
module Main where

import qualified Data.ByteString.Char8 as B

import FFIFun.Foo

main :: IO ()
main = do
  B.putStrLn "main"
  callMeFromC
  callMeFromHaskell
  return ()
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module FFIFun.Foo where

import qualified Data.ByteString.Char8 as B

foreign import ccall "callMeFromHaskell"
  callMeFromHaskell :: IO ()

foreign export ccall callMeFromC :: IO ()
callMeFromC :: IO ()
callMeFromC = B.putStrLn "callMeFromC"
c.c

#包括
无效callMeFromC(void);
void callMeFromHaskell(void)
{
printf(“callMeFromHaskell\n”);
callMeFromC();
}
FFIFun/Foo.hs

{-# LANGUAGE OverloadedStrings #-}
module Main where

import qualified Data.ByteString.Char8 as B

import FFIFun.Foo

main :: IO ()
main = do
  B.putStrLn "main"
  callMeFromC
  callMeFromHaskell
  return ()
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module FFIFun.Foo where

import qualified Data.ByteString.Char8 as B

foreign import ccall "callMeFromHaskell"
  callMeFromHaskell :: IO ()

foreign export ccall callMeFromC :: IO ()
callMeFromC :: IO ()
callMeFromC = B.putStrLn "callMeFromC"
生成文件

SHELL:=bash
GHC_OPT:=-Wall-O2-fno警告未使用的do绑定
大家:好的
测试:ffiso
./$<
ffiso:ffiso.hs c.c
ghc——制作$(ghc_OPT)$^-o$@
清洁:
rm-rf*{.hi,o,_stub.*}ffiso FFIFun/*{.hi,.o,_stub.*}
ghci:ffiso
ghci-通过testring FFIFun/Foo.o c.o FFISo.hs打包
你也会发现

所以,我现在的问题是:

$make ghci
[...]
好的,加载的模块:Main,FFIFun.Foo。
主前奏曲>--好的,正在加载。
主前奏曲>:t callMeFromC
:1:1:不在范围内:`callMeFromC'
序曲主调>--嗯,为什么?
主序曲>:t主序曲
main::IO()
主序曲>主序曲
GHCi运行时链接器:致命错误:我找到了符号的重复定义
FFIFunziFoo_callMeFromC_信息
在处理对象文件时
/FFIFun/Foo.o
这可能是由于:
*加载两个输出相同符号的不同对象文件
*在GHCi命令行上指定同一对象文件两次
*“package.conf”项不正确,导致某些对象被删除
装了两次。
在这种情况下,GHCi无法安全地继续。现在退出。很抱歉
Hrmpf,这里怎么了?有趣的是,我在
i686
上得到了一个不同的错误(上面是
x86\u 64
系统,但都是GHC 7.4.1):

GHCi运行时链接器:致命错误:我找到了符号的重复定义
__斯特吉尼特·菲芬齐福
在处理对象文件时
/FFIFun/Foo.o
这可能是由于:
*加载两个输出相同符号的不同对象文件
*在GHCi命令行上指定同一对象文件两次
*“package.conf”项不正确,导致某些对象被删除
装了两次。
在这种情况下,GHCi无法安全地继续。现在退出。很抱歉
还有,有关于它的文档吗?我觉得我是唯一一个在FFI和GHCi方面有困难的人

编辑: 请注意,
make test
工作正常:

$ghc--make-Wall-O2-fno警告未使用的do bind FFISo.hs c.c-o FFISo
[1/2]编译FFIFun.Foo(FFIFun/Foo.hs,FFIFun/Foo.o)
[2/2]编译Main(FFISo.hs,FFISo.o)
所以。。。
/菲索
主要的
callMeFromC
哈斯克尔
callMeFromC
这是字节码解释器GHCi中的动态链接对象文件

如果加载针对给定C对象静态链接的编译代码,然后还动态解释某些Haskell,这些Haskell也通过FFI引用同一个C对象,则运行时链接器将被迫动态加载C对象

现在,您的地址空间中有两个版本的C符号,失败接踵而至


您必须在GHCi模式下解释所有内容,或者放弃在此过程中使用GHCi。对于某些操作系统链接器,可以通过动态表(
-x
标志)公开静态链接的符号表

如果您尝试将模块与FFI符号静态链接,则可能会出现这种情况;并动态加载。你能详细说明一下吗?或者如何解决这个问题呢?我对它进行了一些尝试,它似乎是GHCi中的一个bug。符号会被查看两次:一次是因为它通过.o文件加载到命令行上,另一次是因为加载了.hs文件。似乎是这样。也许它在启动ghci时根本不应该链接,但只有在执行东西时才应该链接?谢谢你的评论。与此同时,我从7.4.1升级到7.4.2,现在收到了一条不同的错误消息,在x86_64上我甚至没有收到提示(但在x86上我有)。唉。奇怪的是,我在我的项目中修复了这个问题(仅限x86,请参见makefile),但在上面的要点中我无法修复它。这真的很奇怪,也许我应该报告一个GHC bug或其他什么。另请参见和。回答很好。尽管我无法确定在使用GHC api和
dynCompileExpr
时,设置
-x
标志需要什么。我猜,
ghcLink
(在调用
setSessionDynFlags
)可能会有一些值,但到目前为止没有运气。可能需要为“父”会话设置标志。