Скомпилированные библиотеки Haskell с импортом FFI недопустимы при импорте в GHCI - PullRequest
2 голосов
/ 02 мая 2010

Я использую GHC 6.12.1, в Ubuntu 10.04

Когда я пытаюсь использовать синтаксис 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"

Ответы [ 2 ]

1 голос
/ 09 июля 2010

Вы столкнулись с этой ошибкой . Скомпилируйте ваш код с помощью -fPIC, чтобы обойти его.

1 голос
/ 02 мая 2010

Я не могу воспроизвести это ни с 6.10.4, ни с 6.12.1 на Linux x86.(пожалуйста, отредактируйте ваш вопрос, чтобы подтвердить архитектуру, на которой вы видите это, 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"
...