Alex Rivera | Logout

GHCi runtime linker issue when using FFI declarations

Asked 2012-05-18T18:44:59.167
50

I have a problem regarding FFI in Haskell and the interactive mode of GHC again.

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

and a 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

you find it also here as a gist.

So, my problem now:

$ 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 duplic
Edit
Report

1 Answer

3

This is a known limitation of dynamic linking object files in the bytecode interpreter, GHCi.

If you load compiled code that was statically linked against a given C object, and then also interpret some Haskell on the fly that also refers via the FFI to the same C object, the runtime linker will be forced to load the C object dynamically.

Now you have two versions of the C symbol in your address space, and failures ensue.

You must either interpret everything under GHCi mode, or abandon using GHCi for this process. For some OS linkers, you can expose the statically linked symbol table via the dynamic table, (the -x flag).

answered 2013-01-16T14:20:52.860

Your Answer