2012-05-18 18 views
51

Tengo un problema con respecto a FFI en Haskell y el modo interactivo de GHC again.Problema del enlazador de tiempo de ejecución de GHCi al usar las declaraciones FFI

Considere 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" 

y una 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 

lo encuentras también en here as a gist.

lo tanto, mi problema ahora:

$ 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, lo que está mal aquí? Curiosamente me sale un error diferente en i686 (arriba, es un sistema x86_64, pero ambos 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. 

Además, ¿hay algún tipo de documentación al respecto? Siento que soy el único que tiene problemas con FFI y GHCi.

edición: nota, que make test funciona bien:

$ 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

Puede entrar en situaciones si intenta vincular estáticamente un módulo con un símbolo FFI; y también lo carga dinámicamente. –

+0

puede elaborar? o ¿cómo puede uno resolver esto? –

+3

Jugué un poco con él y parece ser un error en GHCi. El símbolo se mira dos veces: una vez porque está cargado en la línea de comando a través del archivo .o, y una vez porque se carga el archivo .hs. Parece. Tal vez no debería vincular en absoluto cuando se inicia ghci, ¿pero solo cuando se ejecutan cosas? –

Respuesta

3

Ésta es a known limitation de archivos objeto de enlace dinámico en el intérprete de código de bytes, GHCi.

Si carga código compilado que estaba enlazado estáticamente contra un objeto C determinado, y luego también interpreta algo de Haskell sobre la marcha que también hace referencia a través del FFI al mismo objeto C, el enlazador de tiempo de ejecución tendrá que cargar la C objeto dinámicamente

Ahora tiene dos versiones del símbolo C en su espacio de direcciones, y se producen fallas.

Debe interpretar todo en modo GHCi o abandonar el uso de GHCi para este proceso. Para algunos enlazadores OS, puede exponer la tabla de símbolos enlazados estáticamente a través de la tabla dinámica (la bandera -x).

+0

[Esta es su otra respuesta a una pregunta similar ] (http://stackoverflow.com/a/13398390/439034). Buena respuesta. Aunque no puedo entender qué configuración conllevaría la bandera '-x' cuando se trabaja con la API aph y' dynCompileExpr'. Supongo que algún valor para 'ghcLink' (en la llamada a' setSessionDynFlags') podría hacerlo pero hasta ahora no tuve suerte. Tal vez la bandera necesita establecerse para la sesión "principal". – worldsayshi

Cuestiones relacionadas