2015-11-20 80 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"一個會話來彌補。