GHCi不适用于FFI导出声明/共享库 [英] GHCi doesn't work with FFI export declarations/shared libraries
问题描述
我在Haskell的FFI和GHC的交互模式方面存在问题。
$ b (源代码也可以通过 gist ):
FFISo.hs:
{ - #LANGUAGE OverloadedStrings# - }
{ - #LANGUAGE ForeignFunctionInterface# - }
模块Main其中
导入合格的Data.ByteString.Char8作为B
外部导入ccallcallMeFromHaskell
callMeFromHaskell :: IO()
外部导出ccall callMeFromC :: IO ()
callMeFromC :: IO()
callMeFromC = B.putStrLncallMeFromC
$ b $ main :: IO()
main = do
B .putStrLnmain
callMeFromHaskell
return()
cc:
#include
void callMeFromC(void);
void callMeFromHaskell(void)
{
printf(callMeFromHaskell\\\
);
callMeFromC();
}
Makefile:
GHC_OPT:= -Wall -O2 -fno-warn -unused-do-bind
全部:ffiso
测试:ffiso
./$<
ffiso:FFISo.hs cc
ghc --make $(GHC_OPT)$ ^ -o $ @
clean:
rm -rf * .hi * .o ffiso * _stub。*
ghci0:ffiso
echo main | ghci FFISo.hs
ghci1:ffiso
echo main | ghci FFISo.hs c.o
ghci2:ffiso
echo main | ghci FFISo.hs co FFISo.o
编译和链接工作正常:
$ make test
ghc --make -Wall -O2 -fno-warn -unused-do-bind FFISo.hs cc -o ffiso
[1的1]编译主(FFISo.hs,FFISo.o)
链接ffiso ...
./ffiso
主
callMeFromHaskell
callMeFromC
但是,如果我想使用GHCi,它会失败并显示以下消息:
$ make ghci0
echo main | ghci FFISo.hs
GHCi,版本7.4.1:http://www.haskell.org/ghc/:?寻求帮助
加载包ghc-prim ...链接...完成。
加载包integer-gmp ...链接...完成。
加载程序包库...链接...完成。
好的,加载的模块:Main。
Prelude Main>加载包bytestring-0.9.2.1 ...正在链接...完成。
< interactive> ;: FFISo.o:未知符号`callMeFromHaskell'
Prelude Main>离开GHCi。
好吧,让我们试着给GHCi co </ code> objectfile。
$ make ghci1
echo main | ghci FFISo.hs c.o
GHCi,版本7.4.1:http://www.haskell.org/ghc/:?寻求帮助
加载包ghc-prim ...链接...完成。
加载包integer-gmp ...链接...完成。
加载程序包库...链接...完成。
加载对象(静态)co ...完成
ghc:co:未知符号`callMeFromC'
链接额外库/对象失败
make:*** [ghci1]错误1
最终链接...
哦好吧...让我们试试FFISo.o :
$ make ghci2
echo main | ghci FFISo.hs c.o FFISo.o
GHCi,版本7.4.1:http://www.haskell.org/ghc/:?寻求帮助
加载包ghc-prim ...链接...完成。
加载包integer-gmp ...链接...完成。
加载程序包库...链接...完成。
加载对象(静态)co ...完成
加载对象(静态)FFISo.o ...完成
ghc:FFISo.o:未知符号`bytestringzm0zi9zi2zi1_DataziByteStringziInternal_PS_con_info'
链接额外的库/对象失败
make:*** [ghci2]错误1
最终链接...
这就是我被卡住的地方。
我测试了两种不同的环境,结果相同:
$#system 1
$ ghc --version
Glorious Glasgow Haskell编译系统,版本7.4.1
$ uname -a
Linux Phenom 3.2.13-1-ARCH#1 SMP PREEMPT Sat Mar 24 09:10:39 CET 2012 x86_64 AMD Phenom(tm)II X6 1055T处理器AuthenticAMD GNU / Linux
$#system 2
$ ghc --version
Glorious Glasgow Haskell编译系统,版本6.12.1
$ uname -a
Linux hermann 2.6.32 -22-generic-pae#36-Ubuntu SMP Thu Jun 3 23:14:23 UTC 2010 i686 GNU / Linux
在调用GHCi时需要指定更多的对象,因为C对象 co </ code>在连接时特别挑剔首先,你需要添加
bytestring
包的目标文件。这是通过在GHCi命令行中添加 -package bytestring
来完成的。
callMeFromC
的目标文件。编译 FFISo.hs
时,它不会生成导出 callMeFromC
的目标文件。它改为使用GHC命名约定并导出 Main_zdfcallMeFromCzuak4_closure
,它实际上是一个静态全局变量,指向包含实际函数定义和环境的闭包/thunk。这是因为你不能写这样的东西: foregin export ccall foo :: IO()
foo = undefined
...并且一旦程序启动就会导致运行时崩溃,因为function值的 foo
无法评估。
GHC生成一个存根文件,其中包含用于从C调用Haskell函数的C代码。此文件被调用 总而言之,调用GHCi时需要使用以下命令行: I have a problem regarding FFI in Haskell and the interactive mode of GHC. (Source is also available via a gist): FFISo.hs:
c.c:
Makefile:
Compiling and linking works fine:
However, if I want to use GHCi, it fails with this message:
Well, let's try giving GHCi the Oh okay... let's try with FFISo.o:
And that's where I'm stuck. I tested it with two different environments with the same result:
You need to specify some more objects to link when invoking GHCi, because the C object First, you need to add the Then, you need to add the actual object file that defines ...and have the runtime crash as soon as the program starts because the "function value" of GHC generates a stub file, which contains C code for calling the Haskell function from C. This file is called All in all, you need to use this command line when invoking GHCi:
这篇关于GHCi不适用于FFI导出声明/共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! FFISo_stub.c
,并为您编译为 FFISo_stub.o
。该目标文件导出可以直接调用的
ghci -package bytestring FFISo.o co FFISo_stub.o FFISo.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module Main 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"
main :: IO ()
main = do
B.putStrLn "main"
callMeFromHaskell
return ()
#include <stdio.h>
void callMeFromC(void);
void callMeFromHaskell(void)
{
printf("callMeFromHaskell\n");
callMeFromC();
}
GHC_OPT := -Wall -O2 -fno-warn-unused-do-bind
all: ffiso
test: ffiso
./$<
ffiso: FFISo.hs c.c
ghc --make $(GHC_OPT) $^ -o $@
clean:
rm -rf *.hi *.o ffiso *_stub.*
ghci0: ffiso
echo main | ghci FFISo.hs
ghci1: ffiso
echo main | ghci FFISo.hs c.o
ghci2: ffiso
echo main | ghci FFISo.hs c.o FFISo.o
$ make test
ghc --make -Wall -O2 -fno-warn-unused-do-bind FFISo.hs c.c -o ffiso
[1 of 1] Compiling Main ( FFISo.hs, FFISo.o )
Linking ffiso ...
./ffiso
main
callMeFromHaskell
callMeFromC
$ make ghci0
echo main | ghci FFISo.hs
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Ok, modules loaded: Main.
Prelude Main> Loading package bytestring-0.9.2.1 ... linking ... done.
<interactive>: FFISo.o: unknown symbol `callMeFromHaskell'
Prelude Main> Leaving GHCi.
c.o
objectfile.
$ make ghci1
echo main | ghci FFISo.hs c.o
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading object (static) c.o ... done
ghc: c.o: unknown symbol `callMeFromC'
linking extra libraries/objects failed
make: *** [ghci1] Error 1
final link ...
$ make ghci2
echo main | ghci FFISo.hs c.o FFISo.o
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading object (static) c.o ... done
Loading object (static) FFISo.o ... done
ghc: FFISo.o: unknown symbol `bytestringzm0zi9zi2zi1_DataziByteStringziInternal_PS_con_info'
linking extra libraries/objects failed
make: *** [ghci2] Error 1
final link ...
$ # system 1
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.4.1
$ uname -a
Linux phenom 3.2.13-1-ARCH #1 SMP PREEMPT Sat Mar 24 09:10:39 CET 2012 x86_64 AMD Phenom(tm) II X6 1055T Processor AuthenticAMD GNU/Linux
$ # system 2
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.12.1
$ uname -a
Linux hermann 2.6.32-22-generic-pae #36-Ubuntu SMP Thu Jun 3 23:14:23 UTC 2010 i686 GNU/Linux
c.o
is particularly picky when it comes to linking order.bytestring
package's object files. This is done by adding -package bytestring
to the GHCi command line.callMeFromC
. When FFISo.hs
is compiled, it doesn't produce an object file that exports callMeFromC
. It instead uses the GHC naming convention and exports Main_zdfcallMeFromCzuak4_closure
, which actually is a static global variable pointing to the closure/"thunk" that contains the actual function definition and environment. This is so that you can't write something like this:foregin export ccall foo :: IO ()
foo = undefined
foo
can't be evaluated. The function definition is only inspected once the function is actually used.FFISo_stub.c
, and is compiled into FFISo_stub.o
for you. This object file exports the "C version" of callMeFromC
that can be called directly. Feel free to inspect the generated code, it is quite interesting.ghci -package bytestring FFISo.o c.o FFISo_stub.o FFISo.hs