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

I am using GHC 6.12.1, on Ubuntu 10.04

When I try to use the FFI syntax for static storage, only modules that work in interpreted mode (i.e. GHCI) work. The compiled modules have invalid pointers and do not work. I would like to know if anyone can reproduce the problem, whether it is a bug in my code or GHC, and (if the latter) if this is a known problem.

I am using sys_siglist

it because it is present in the standard library on my system, but I do not believe the actual contents of the repository (I discovered this while writing the libidn binding). If it helps, it sys_siglist

is defined <signal.h>

as:

extern __const char *__const sys_siglist[_NSIG];

      

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

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

      

However, an import that will not change the result and the call printf()

prints the same pointer value as show siglist_a

.

My suspicion is that this is due to static and dynamic loading of the library.

Update: someone from #haskell suggested it might be 64-bit; if anyone tries to reproduce it, can you please indicate your architecture and does it work in the comment?

Enter the 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 ​​are 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 (c 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"

      

+2


a source to share


2 answers


You meet this error . Compile your code with -fPIC

to work around it.



+1


a source


I cannot reproduce this with 6.10.4 or 6.12.1 on Linux x86. (please edit your question to confirm that the architecture you are seeing this on is x86-64)



[tommd@Mavlo Test]$ ghc-6.12.1 --make irc.hs
[1 of 3] Compiling B                ( B.hs, B.o )
[2 of 3] Compiling A                ( A.hs, A.o )
[3 of 3] Compiling Main             ( irc.hs, irc.o )
Linking irc ...
[tommd@Mavlo Test]$ ./irc
siglist_a    = 0x080ab4c0
siglist_b    = 0x080ab4c0
siglist_main = 0x080ab4c0
siglist_a   [2] = Just "Interrupt"
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"
[tommd@Mavlo Test]$ ghc-6.10.4 irc.hs --make
[1 of 3] Compiling A                ( A.hs, A.o )
[2 of 3] Compiling B                ( B.hs, B.o )
[3 of 3] Compiling Main             ( irc.hs, irc.o )
Linking irc ...
[tommd@Mavlo Test]$ ./irc
siglist_a    = 0x0809ec80
siglist_b    = 0x0809ec80
siglist_main = 0x0809ec80
siglist_a   [2] = Just "Interrupt"
siglist_b   [2] = Just "Interrupt"
siglist_main[2] = Just "Interrupt"

      

+1


a source







All Articles