2

我在 Ubuntu 10.04 中使用 GHC 6.12.1

当我尝试使用 FFI 语法进行静态存储时,只有以解释模式(即 GHCI)运行的模块才能正常工作。编译的模块有无效的指针,并且不工作。我想知道是否有人可以重现该问题,这是否是我的代码或 GHC 中的错误,以及(如果是后者)是否是已知问题。

我正在使用sys_siglist它,因为它存在于我系统上的标准库中,但我不相信实际使用的存储很重要(我在编写与 libidn 的绑定时发现了这一点)。如果有帮助,sys_siglist定义<signal.h>为:

extern __const char *__const sys_siglist[_NSIG];

我认为这种类型可能是问题所在,所以我也尝试将它包装在一个普通的 C 过程中:

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

但是,导入不会改变结果,并且printf()调用会打印与show siglist_a.

我怀疑这与静态和动态库加载有关。

更新:#haskell 中有人建议这可能是 64 位特定的;如果有人试图复制它,您能否在评论中提及您的架构以及它是否有效?

代码如下:

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

我希望得到类似这样的输出,其中所有指针值都相同且有效:

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

但是,如果我编译 A.hs(带有ghc -c A.hs),则输出将更改为:

$ 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"
4

2 回答 2

1

我无法在 Linux x86 上使用 6.10.4 或 6.12.1 重现此问题。(请编辑您的问题以确认您看到的架构是 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"
于 2010-05-01T23:56:06.913 回答
1

您遇到了这个错误。编译您的代码-fPIC以解决它。

于 2010-07-08T21:25:45.710 回答