2012-05-18 2 views
51

하스켈에서 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' 플래그가 어떤 설정을해야 하는지를 알 수는 없지만. 나는'setSessionDynFlags'에 대한 호출에서'ghcLink'에 대한 어떤 가치가 있다고 생각합니다.하지만 지금까지는 그렇게 할 수 없습니다. 플래그는 "상위"세션에 대해 설정되어야합니다. – worldsayshi

관련 문제