2015-11-20 47 views
1

我最近一直在与伊德里斯搞混,并决定尝试与其Network.Socket库玩。我启动了REPL,导入了模块,并使用socket命令创建了一个套接字。在试图执行IO操作,我遇到了以下错误:伊德里斯FFI“找不到符号”

failed to construct ffun from (Builtins.MkPair (FFI_C.C_Types (Int)) (Int) (FFI_C.C_IntT (Int) (FFI_C.C_IntNative)) (2),Builtins.MkPair (FFI_C.C_Types (Int)) (Int) (FFI_C.C_IntT (Int) (FFI_C.C_IntNative)) (1),[]) 
Symbol "socket" not found 
user error (Could not call foreign function "socket" with args [2,1,0]) 

要查看问题是否Network.Socket具体,或者只是FFI在一般情况下,我做了一个虚函数。

printf : String -> IO() 
printf = foreign FFI_C "printf" (String -> IO()) 

执行的:x printf "Hello World"产生类似的错误:

Symbol "printf" not found 
user error (Could not call foreign function "printf" with args ["hello world"]) 

尽管这一切,putStr工作正常。

我正在运行Idris 9.20,通过在编译时设置的-f FFI与cabal安装。我正在使用通过MacPorts安装的libffi 3.4版本。

+0

我得到了与通过brew安装的idris 0.9.20.1相同的错误,但是将printf放入main并调用:exec使用警告。 – Markus

回答

2

我认为这与Idris FFI根据代码是否被编译或解释而操作不同有关。当编译代码时,FFI要求在C代码阶段,命名的C函数处于作用域中,并且在链接C可执行文件时,正确的名称被链接到中。由于Idris的RTS与libc链接,这使得很多来自libc的名字没有任何额外的努力(某些名字可能需要%include来确保包含正确的C头文件才能将它们放在范围内)。当解释代码时,解释器会在已动态加载的库列表中查找FFI调用,这需要一个不同的指令:文件中的%dynamic或解释器中的:dynamic。默认情况下,没有加载动态库,所以即使libc中的标准名称也不在范围内。这可以通过在文件中包含%dynamic "libc"或在REPL命令行中使用:dynamic "libc"一个会话来弥补。