2012-04-12 10 views
7

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

(स्रोत भी एक gist माध्यम से उपलब्ध है):

FFISo.hs:

{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE ForeignFunctionInterface #-} 
module Main 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" 

main :: IO() 
main = do 
    B.putStrLn "main" 
    callMeFromHaskell 
    return() 

c.c:

#include <stdio.h> 

void callMeFromC(void); 

void callMeFromHaskell(void) 
{ 
    printf("callMeFromHaskell\n"); 
    callMeFromC(); 
} 

Makefile:

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 ffiso *_stub.* 

ghci0: ffiso 
    echo main | ghci FFISo.hs 

ghci1: ffiso 
    echo main | ghci FFISo.hs c.o 

ghci2: ffiso 
    echo main | ghci FFISo.hs c.o FFISo.o 

संकलन और जोड़ने ठीक काम करता है:

$ make test 
ghc --make -Wall -O2 -fno-warn-unused-do-bind FFISo.hs c.c -o ffiso 
[1 of 1] Compiling Main    (FFISo.hs, FFISo.o) 
Linking ffiso ... 
./ffiso 
main 
callMeFromHaskell 
callMeFromC 

हालांकि, अगर मैं GHCi उपयोग करना चाहते हैं, यह इस संदेश के साथ विफल रहता है:

$ make ghci0 
echo main | ghci FFISo.hs 
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Ok, modules loaded: Main. 
Prelude Main> Loading package bytestring-0.9.2.1 ... linking ... done. 
<interactive>: FFISo.o: unknown symbol `callMeFromHaskell' 

Prelude Main> Leaving GHCi. 

ठीक है, GHCi c.o objectfile देने की कोशिश करते हैं।

$ make ghci1 
echo main | ghci FFISo.hs c.o 
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Loading object (static) c.o ... done 
ghc: c.o: unknown symbol `callMeFromC' 
linking extra libraries/objects failed 
make: *** [ghci1] Error 1 
final link ... 

ओह ठीक है ... चलो FFISo.o साथ की कोशिश करते हैं:

$ make ghci2 
echo main | ghci FFISo.hs c.o FFISo.o 
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Loading object (static) c.o ... done 
Loading object (static) FFISo.o ... done 
ghc: FFISo.o: unknown symbol `bytestringzm0zi9zi2zi1_DataziByteStringziInternal_PS_con_info' 
linking extra libraries/objects failed 
make: *** [ghci2] Error 1 
final link ... 

और यहीं मैं अटक हूँ।

मैं एक ही परिणाम के साथ दो अलग अलग वातावरण के साथ यह परीक्षण किया:

$ # system 1 
$ ghc --version 
The Glorious Glasgow Haskell Compilation System, version 7.4.1 
$ uname -a 
Linux phenom 3.2.13-1-ARCH #1 SMP PREEMPT Sat Mar 24 09:10:39 CET 2012 x86_64 AMD Phenom(tm) II X6 1055T Processor AuthenticAMD GNU/Linux 

$ # system 2 
$ ghc --version 
The Glorious Glasgow Haskell Compilation System, version 6.12.1 
$ uname -a 
Linux hermann 2.6.32-22-generic-pae #36-Ubuntu SMP Thu Jun 3 23:14:23 UTC 2010 i686 GNU/Linux 

उत्तर

10

आप जब GHCi लागू लिंक करने के लिए कुछ और वस्तुओं निर्दिष्ट करने की आवश्यकता है, क्योंकि सी वस्तु c.o विशेष रूप से picky है यह जोड़ने की बात आती है जब आदेश।

सबसे पहले, आपको bytestring पैकेज की ऑब्जेक्ट फ़ाइलों को जोड़ने की आवश्यकता है। यह GHCi कमांड लाइन में -package bytestring जोड़ कर किया जाता है।

फिर, आपको वास्तविक ऑब्जेक्ट फ़ाइल जोड़ने की आवश्यकता है जो callMeFromC को परिभाषित करता है। जब FFISo.hs संकलित किया जाता है, तो यह ऑब्जेक्ट फ़ाइल उत्पन्न नहीं करता है जो callMeFromC निर्यात करता है। इसके बजाय यह जीएचसी नामकरण सम्मेलन का उपयोग करता है और Main_zdfcallMeFromCzuak4_closure निर्यात करता है, जो वास्तव में एक स्थाई वैश्विक चर है जो बंद/"थंक" को इंगित करता है जिसमें वास्तविक कार्य परिभाषा और पर्यावरण शामिल है। यह वह जगह है, ताकि आप कुछ इस तरह नहीं लिख सकते हैं:

foregin export ccall foo :: IO() 
foo = undefined 

... और जैसे ही कार्यक्रम शुरू होता है क्योंकि foo की "समारोह मूल्य" का मूल्यांकन नहीं किया जा सकता है क्रम दुर्घटना है। फ़ंक्शन परिभाषा का केवल निरीक्षण किया जाता है जब फ़ंक्शन वास्तव में उपयोग किया जाता है।

जीएचसी एक स्टब फ़ाइल उत्पन्न करता है, जिसमें सी से कोडल हास्केल फ़ंक्शन को कॉल करने के लिए सी कोड शामिल है। इस फ़ाइल को FFISo_stub.c कहा जाता है, और आपके लिए FFISo_stub.o में संकलित किया गया है। यह ऑब्जेक्ट फ़ाइल callMeFromC के "सी संस्करण" को निर्यात करती है जिसे सीधे कहा जा सकता है। जेनरेट कोड का निरीक्षण करने के लिए स्वतंत्र महसूस करें, यह काफी रोचक है।

कुल मिलाकर, आप जब GHCi लागू इस आदेश पंक्ति का उपयोग करने की जरूरत है:

ghci -package bytestring FFISo.o c.o FFISo_stub.o FFISo.hs 
संबंधित मुद्दे