Compiled Haskell libraries with FFI imports are invalid when imported into GHCI

Posted by John Millikin on Stack Overflow See other posts from Stack Overflow or by John Millikin
Published on 2010-05-01T23:34:46Z Indexed on 2010/05/02 1:07 UTC
Read the original article Hit count: 326

Filed under:
|

I am using GHC 6.12.1, in Ubuntu 10.04

When I try to use the FFI syntax for static storage, only modules running in interpreted mode (ie GHCI) work properly. Compiled modules have invalid pointers, and do not work. I'd like to know whether anybody can reproduce the problem, whether this an error in my code or GHC, and (if the latter) whether it's a known issue.

I'm using sys_siglist because it's present in a standard library on my system, but I don't believe the actual storage used matters (I discovered this while writing a binding to libidn). If it helps, sys_siglist is defined in <signal.h> as:

extern __const char *__const sys_siglist[_NSIG];

I thought this type might be the problem, so I also tried wrapping it in a plain C procedure:

#include<stdio.h>
const char **test_ffi_import()
{
    printf("C think sys_siglist = %X\n", sys_siglist);
    return sys_siglist;
}

However, importing that doesn't change the result, and the printf() call prints the same pointer value as show siglist_a.

My suspicion is that it's something to do with static and dynamic library loading.

Update: somebody in #haskell suggested this might be 64-bit specific; if anybody tries to reproduce it, can you mention your architecture and whether it worked in a comment?

Code as follows:

-- A.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module A where
import Foreign
import Foreign.C

foreign import ccall "&sys_siglist"
    siglist_a :: Ptr CString

--

-- B.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module B where
import Foreign
import Foreign.C

foreign import ccall "&sys_siglist"
    siglist_b :: Ptr CString

--

-- Main.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign
import Foreign.C
import A
import B

foreign import ccall "&sys_siglist"
    siglist_main :: Ptr CString

main = do
    putStrLn $ "siglist_a    = " ++ show siglist_a
    putStrLn $ "siglist_b    = " ++ show siglist_b
    putStrLn $ "siglist_main = " ++ show siglist_main

    peekSiglist "a   " siglist_a
    peekSiglist "b   " siglist_b
    peekSiglist "main" siglist_main

peekSiglist name siglist = do
    ptr <- peekElemOff siglist 2
    str <- maybePeek peekCString ptr
    putStrLn $ "siglist_" ++ name ++ "[2] = " ++ show str

I would expect something like this output, where all pointer values identical and valid:

$ runhaskell Main.hs 
siglist_a    = 0x00007f53a948fe00
siglist_b    = 0x00007f53a948fe00
siglist_main = 0x00007f53a948fe00
siglist_a   [2] = Just "Interrupt"
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"

However, if I compile A.hs (with ghc -c A.hs), then the output changes to:

$ runhaskell Main.hs 
siglist_a    = 0x0000000040378918
siglist_b    = 0x00007fe7c029ce00
siglist_main = 0x00007fe7c029ce00
siglist_a   [2] = Nothing
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"

© Stack Overflow or respective owner

Related posts about haskell

Related posts about ffi