2012-05-18 22 views
51

我對Haskell中的FFI和GHC again的交互模式有問題。使用FFI聲明時的GHCi運行時鏈接程序問題

考慮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() 

c.c

#include <stdio.h> 

void callMeFromC(void); 

void callMeFromHaskell(void) 
{ 
    printf("callMeFromHaskell\n"); 
    callMeFromC(); 
} 

FFIFun/Foo.hs

{-# 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" 

Makefile

SHELL := bash 

GHC_OPT := -Wall -O2 -fno-warn-unused-do-bind 


all: ffiso 

test: ffiso 
    ./$< 

ffiso: FFISo.hs c.c 
    ghc --make $(GHC_OPT) $^ -o [email protected] 

clean: 
    rm -rf *{.hi,o,_stub.*} ffiso FFIFun/*{.hi,.o,_stub.*} 

ghci: ffiso 
    ghci -package bytestring FFIFun/Foo.o c.o FFISo.hs 

您還可以找到它here as a gist

所以,現在我的問題:

$ make ghci 
[...] 
Ok, modules loaded: Main, FFIFun.Foo. 
Prelude Main> -- fine, it's loading. 
Prelude Main> :t callMeFromC 

<interactive>:1:1: Not in scope: `callMeFromC' 
Prelude Main> -- uhm, why? 
Prelude Main> :t main 
main :: IO() 
Prelude Main> main 


GHCi runtime linker: fatal error: I found a duplicate definition for symbol 
    FFIFunziFoo_callMeFromC_info 
whilst processing object file 
    ./FFIFun/Foo.o 
This could be caused by: 
    * Loading two different object files which export the same symbol 
    * Specifying the same object file twice on the GHCi command line 
    * An incorrect `package.conf' entry, causing some object to be 
    loaded twice. 
GHCi cannot safely continue in this situation. Exiting now. Sorry. 

Hrmpf,這裏有什麼問題?有趣的是我在i686得到一個不同的錯誤(上面,這是一個x86_64系統,但兩者GHC 7.4.1):

GHCi runtime linker: fatal error: I found a duplicate definition for symbol 
    __stginit_FFIFunziFoo 
whilst processing object file 
    ./FFIFun/Foo.o 
This could be caused by: 
    * Loading two different object files which export the same symbol 
    * Specifying the same object file twice on the GHCi command line 
    * An incorrect `package.conf' entry, causing some object to be 
    loaded twice. 
GHCi cannot safely continue in this situation. Exiting now. Sorry. 

此外,有一些關於它的文件?我覺得我是唯一一個在FFI和GHCi那裏遇到困難的人。

編輯: 注,即make test正常工作:

$ ghc --make -Wall -O2 -fno-warn-unused-do-bind FFISo.hs c.c -o ffiso 
[1 of 2] Compiling FFIFun.Foo  (FFIFun/Foo.hs, FFIFun/Foo.o) 
[2 of 2] Compiling Main    (FFISo.hs, FFISo.o) 
Linking ffiso ... 
./ffiso 
main 
callMeFromC 
callMeFromHaskell 
callMeFromC 
+0

如果您嘗試將模塊靜態鏈接到FFI符號,則可能會遇到這種情況;並動態加載它。 –

+0

你能詳細說明嗎?或者如何解決這個問題? –

+3

我玩了一下,它似乎是GHCi中的錯誤。該符號被查看兩次:一次是因爲它通過.o文件加載到命令行,另一次是因爲加載了.hs文件。它似乎。也許它不應該在啓動ghci時連接,但只有在執行時纔會鏈接。 –

回答

3

這是在字節碼解釋器,GHCI動態鏈接對象文件a known limitation

如果您加載的是靜態鏈接到給定C對象的編譯代碼,然後還通過FFI指向同一個C對象來動態解釋某個Haskell,則運行時鏈接程序將被強制加載C對象動態。

現在,您的地址空間中有兩個C符號版本,隨後出現故障。

您必須在GHCi模式下解釋所有內容,或者放棄在此過程中使用GHCi。對於某些OS鏈接器,可以通過動態表(-x標誌)公開靜態鏈接的符號表。

+0

[以下是對類似問題的其他回覆](http://stackoverflow.com/a/13398390/439034)。好的迴應。雖然我無法弄清楚在使用GHC api和dynCompileExpr時設置'-x'標誌的設置。我猜''ghcLink'的一些值(在調用'setSessionDynFlags'時)可能會做到這一點,但迄今沒有運氣。也許該標誌需要設置爲「父」會話。 – worldsayshi