Вопрос по haskell, linker – Проблема компоновщика среды выполнения GHCi при использовании объявлений FFI

51

У меня проблема с FFI в Haskell и интерактивным режимом GHCснова.

Рассматривать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"

и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 [email protected]

clean:
    rm -rf *{.hi,o,_stub.*} ffiso FFIFun/*{.hi,.o,_stub.*}

ghci: ffiso
    ghci -package bytestring FFIFun/Foo.o c.o FFISo.hs

Вы также найдете этоздесь как суть.

Итак, моя проблема сейчас:

$ 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 duplicate definition for symbol
   FFIFunziFoo_callMeFromC_info
whilst processing object file
   ./FFIFun/Foo.o
This could be caused by:
   * Loading two different object files which export the same symbol
   * Specifying the same object file twice on the GHCi command line
   * An incorrect `package.conf' entry, causing some object to be
     loaded twice.
GHCi cannot safely continue in this situation.  Exiting now.  Sorry.

Hrmpf, что здесь не так? Интересно, я получаю другую ошибку наi686 (выше, этоx86_64 система, но оба GHC 7.4.1):

GHCi runtime linker: fatal error: I found a duplicate definition for symbol
   __stginit_FFIFunziFoo
whilst processing object file
   ./FFIFun/Foo.o
This could be caused by:
   * Loading two different object files which export the same symbol
   * Specifying the same object file twice on the GHCi command line
   * An incorrect `package.conf' entry, causing some object to be
     loaded twice.
GHCi cannot safely continue in this situation.  Exiting now.  Sorry.

Кроме того, есть ли какая-либо документация по этому поводу? Я чувствую, что я единственный, кто испытывает трудности с FFI и GHCi.

редактировать: Обратите внимание, чтоmake test работает отлично:

$ ghc --make -Wall -O2 -fno-warn-unused-do-bind FFISo.hs c.c -o ffiso
[1 of 2] Compiling FFIFun.Foo       ( FFIFun/Foo.hs, FFIFun/Foo.o )
[2 of 2] Compiling Main             ( FFISo.hs, FFISo.o )
Linking ffiso ...
./ffiso
main
callMeFromC
callMeFromHaskell
callMeFromC
Вы можете попасть в ситуации, если попытаетесь статически связать модуль с символом FFI; а также динамически загружать его. Don Stewart
можешь уточнить? или как можно решить это? h_s
Спасибо за ваш комментарий. тем временем я обновился с 7.4.1 до 7.4.2 и получил другое сообщение об ошибке сейчас, я даже не получаю подсказку на x86_64 (но на x86 я делаю). вздох. как ни странно я исправил проблему в своем проекте (wien.tomnetworks.com/gitweb/?p=mate.git;a=summary только для x86, смотрите make-файл), но яnot в состоянии исправить это в сущности выше. это действительно странно, вероятно, я должен сообщить об ошибке GHC или что-то в этом роде. lewurm
Я немного поиграл с этим, и это похоже на ошибку в GHCi. Символ рассматривается дважды: один раз, потому что он загружен в командной строке через файл .o, и один раз, потому что загружен файл .hs. Похоже на то. Может быть, он не должен ссылаться вообще при запуске ghci, а только при выполнении чего-либо? Joachim Breitner

Ваш Ответ

1   ответ
3

Этоизвестное ограничение динамического связывания объектных файлов в интерпретаторе байт-кода, GHCi.

Если вы загружаете скомпилированный код, который был статически связан с данным объектом C, а затем также интерпретируете некоторый Haskell на лету, который также обращается через FFI к тому же объекту C, компоновщик времени выполнения будет вынужден загружать объект C динамически.

Теперь у вас есть две версии символа C в вашем адресном пространстве, и происходят сбои.

Вы должны либо интерпретировать все в режиме GHCi, либо отказаться от использования GHCi для этого процесса. Для некоторых компоновщиков ОС вы можете предоставить статически связанную таблицу символов через динамическую таблицу (-x флаг).

Here's your other response to similar questionError: User Rate Limit Exceeded-xError: User Rate Limit ExceededdynCompileExprError: User Rate Limit ExceededghcLinkError: User Rate Limit ExceededsetSessionDynFlagsError: User Rate Limit Exceeded

Похожие вопросы