51 votes

Problème de liaison de l'exécution de GHCi lors de l'utilisation de déclarations FFI

J'ai un problème concernant la FFI en Haskell et le mode interactif de GHC à nouveau .

Pensez à 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"

et un 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 $@

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

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

vous le trouvez aussi voici l'essentiel .

Donc, mon problème maintenant :

$ 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, qu'est-ce qui ne va pas ici ? Il est intéressant de noter que j'obtiens une erreur différente sur i686 (ci-dessus, c'est un x86_64 mais aussi 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.

Existe-t-il une documentation à ce sujet ? J'ai l'impression d'être le seul à avoir des difficultés avec FFI et GHCi.

éditer : note, que make test fonctionne 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

3voto

Don Stewart Points 94361

C'est une limitation connue de lier dynamiquement des fichiers objets dans l'interpréteur bytecode, GHCi.

Si vous chargez du code compilé qui a été lié de manière statique à un objet C donné, et que vous interprétez également du Haskell à la volée qui fait également référence via le FFI au même objet C, l'éditeur de liens d'exécution sera obligé de charger l'objet C de manière dynamique.

Vous avez maintenant deux versions du symbole C dans votre espace d'adressage, et les échecs s'enchaînent.

Vous devez soit interpréter tout en mode GHCi, soit renoncer à utiliser GHCi pour ce processus. Pour certains éditeurs de liens OS, vous pouvez exposer la table de symboles liée statiquement via la table dynamique (la fonction -x drapeau).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X