2012-05-18 12 views
51

मुझे हास्केल में एफएफआई और जीएचसी again के इंटरैक्टिव मोड के बारे में कोई समस्या है।एफएचआई घोषणाओं का उपयोग करते समय जीएचसीआई रनटाइम लिंकर समस्या

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 

आपको यह भी here as a gist लगता है।

तो, अब मेरी समस्या:

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

इसके अलावा, वहाँ इस बारे में कुछ प्रलेखन है? मुझे लगता है कि मैं अकेला हूं जिसने एफएफआई और जीएचसीआई के साथ कठिन समय निकाला है।

संपादित करें: ध्यान दें, कि 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 
+0

यदि आप एफएफआई प्रतीक के खिलाफ मॉड्यूल को स्थिर रूप से लिंक करने का प्रयास करते हैं तो आप परिस्थितियों में जा सकते हैं; और गतिशील रूप से इसे लोड भी करें। –

+0

क्या आप विस्तृत कर सकते हैं? या कोई इसे कैसे हल कर सकता है? –

+3

मैंने इसके साथ थोड़ा सा खेला और यह जीएचसीआई में एक बग प्रतीत होता है। प्रतीक दो बार देखा जाता है: एक बार क्योंकि यह .o फ़ाइल के माध्यम से कमांड लाइन पर लोड होता है, और एक बार क्योंकि .hs फ़ाइल लोड हो जाती है। ऐसा लगता है। शायद यह ghci शुरू करते समय बिल्कुल लिंक नहीं करना चाहिए, लेकिन केवल सामान निष्पादित करते समय? –

उत्तर

3

यह बाईटकोड दुभाषिया, GHCi में गतिशील जोड़ने वस्तु फ़ाइलों के a known limitation है।

यदि आप किसी दिए गए सी ऑब्जेक्ट के साथ स्थिर रूप से जुड़े संकलित कोड को लोड करते हैं, और फिर फ्लाई पर कुछ हास्केल की व्याख्या भी करते हैं जो एफएफआई के माध्यम से उसी सी ऑब्जेक्ट को संदर्भित करता है, तो रनटाइम लिंकर को सी लोड करने के लिए मजबूर किया जाएगा गतिशील रूप से वस्तु।

अब आपके पास अपने पता स्थान में सी प्रतीक के दो संस्करण हैं, और असफलताएं आती हैं।

आपको या तो जीएचसीआई मोड के तहत सब कुछ समझना चाहिए, या इस प्रक्रिया के लिए जीएचसीआई का उपयोग छोड़ देना चाहिए। कुछ ओएस लिंकर्स के लिए, आप गतिशील तालिका के माध्यम से स्थिर रूप से जुड़े प्रतीक तालिका का पर्दाफाश कर सकते हैं, (-x ध्वज)।

+0

[इसी तरह के प्रश्न के लिए आपकी अन्य प्रतिक्रिया यहां दी गई है ] (http://stackoverflow.com/a/13398390/439034)। अच्छी प्रतिक्रिया। हालांकि मैं यह नहीं समझ सकता कि जीएचसी एपीआई और 'dynCompileExpr' के साथ काम करते समय '-x' ध्वज किस सेटिंग को लागू करेगा। मैं 'ghcLink' के लिए कुछ मान अनुमान लगा रहा हूं (' setSessionDynFlags' 'पर कॉल में) ऐसा कर सकता है लेकिन अब तक कोई भाग्य नहीं है। शायद ध्वज को "पैरेंट" सत्र के लिए सेट करने की आवश्यकता है। – worldsayshi

संबंधित मुद्दे