2017-04-10 47 views
3

我有以下Haskell代碼:Data.Aeson與ForeignFunctionInterface在GHC

{-# LANGUAGE OverloadedStrings, DeriveGeneric, DeriveAnyClass #-} 

module BoardToJSON where 

import GHC.Generics 
import Data.Aeson 
import Data.Aeson.Text (encodeToLazyText) 
import Data.Text 
import Control.Applicative 
import Control.Monad 
import qualified Data.ByteString.Lazy as B 
import GHC.Generics 
import Data.Text.Lazy.IO as I 

import Foreign.C.Types 
import Foreign.C.String 
import Data.Maybe 
import Data.List 
import Data.Ix 

import Data.List 
import Data.Maybe 
--foreign export ccall writef :: IO() 

data Piece = Piece { 
    _type :: !Text, 
    _color :: !Text, 
    _x :: Int, 
    _y :: Int 
    } deriving (Eq, Show, Generic, ToJSON, FromJSON) 

piecesList::[Piece] 
piecesList = [Piece "Rook" "White" 1 1, Piece "Knight" "White" 2 1, Piece "Bishop" "White" 3 1, Piece "Queen" "White" 4 1, 
      Piece "King" "White" 5 1, Piece "Bishop" "White" 6 1, Piece "Knight" "White" 7 1, Piece "Rook" "White" 8 1, 
      Piece "Pawn" "White" 1 2, Piece "Pawn" "White" 2 2, Piece "Pawn" "White" 3 2, Piece "Pawn" "White" 4 2, 
      Piece "Pawn" "White" 5 2, Piece "Pawn" "White" 6 2, Piece "Pawn" "White" 7 2, Piece "Pawn" "White" 8 2, 
      Piece "Rook" "Black" 1 8, Piece "Knight" "Black" 2 8, Piece "Bishop" "Black" 3 8, Piece "Queen" "Black" 4 8, 
      Piece "King" "Black" 5 8, Piece "Bishop" "Black" 6 8, Piece "Knight" "Black" 7 8, Piece "Rook" "Black" 8 8, 
      Piece "Pawn" "Black" 1 7, Piece "Pawn" "Black" 2 7, Piece "Pawn" "Black" 3 7, Piece "Pawn" "Black" 4 7, 
      Piece "Pawn" "Black" 5 7, Piece "Pawn" "Black" 6 7, Piece "Pawn" "Black" 7 7, Piece "Pawn" "Black" 8 7] 

jsonFile :: FilePath 
jsonFile = "pieces.json" 

writef = I.writeFile jsonFile (encodeToLazyText piecesList) 

getJSON :: IO B.ByteString 
getJSON = B.readFile jsonFile 

getPieces :: IO (Either String [Piece]) 
getPieces = (eitherDecode <$> getJSON) :: IO (Either String [Piece]) 

aeson安裝有陰謀。

做當:

$ ghci 
Prelude> :load BoardToJSON 
*BoardToJSON> writef 

我正在寫在這片陣列的JSON文件。

然而,當取消註釋foreign export ccall writef :: IO()與編譯:

CPP_SOURCES = main.cpp 
HASKELL_SOURCES = haskell/BoardToJSON.hs 
OBJECTS = haskell/*.o *.o 

main: compileHaskell compileCPP link clean; 

compileHaskell: $(HASKELL_SOURCES); ghc -c -XForeignFunctionInterface -fforce-recomp -O $(HASKELL_SOURCES) 

compileCPP: $(CPP_SOURCES); g++ -c -I/usr/lib/ghc/include -O $(CPP_SOURCES) 

link: ; ghc -o Main -no-hs-main $(OBJECTS) -lstdc++ 

clean: ; rm -rf main && rm -rf haskell/*.o && rm *.o && rm -rf haskell/*.hi && rm -rf haskell/*_stub.h 

compileHaskellcompileCPP去罰款,但我得到了一堆類型的錯誤:

/tmp/ghca1ca_0/ghc_8.o:(.data.rel.ro+0x2a8): undefined reference to `bytestringzm0zi10zi8zi1_DataziByteStringziLazzy_getContents2_closure' 
collect2: error: ld returned 1 exit status 
`gcc' failed in phase `Linker'. (Exit code: 1) 
makefile:12: recipe for target 'link' failed 

我的猜測是, ghc不知道在哪裏可以找到aeson所以我這樣做:

$ sudo echo "/root/.cabal/lib/x86_64-linux-ghc-8.0.2" > /etc/ld.so.conf.d/x86_64-linux-gnu.conf 
$ sudo ldconfig 
$ sudo ldconfig -v | grep -i aeson     
ldconfig: Path `/lib/x86_64-linux-gnu' given more than once 
ldconfig: Path `/usr/lib/x86_64-linux-gnu' given more than once 
ldconfig: /lib/x86_64-linux-gnu/ld-2.24.so is the dynamic linker, ignoring 

libHSaeson-1.1.1.0-4sfmSwjYSZ4CJzSxs6L5hG-ghc8.0.1.so -> libHSaeson-1.1.1.0-4sfmSwjYSZ4CJzSxs6L5hG-ghc8.0.1.so 

沒有機會。

我試圖添加-llibHSaeson-lHSaeson-laeson以鏈接的目標。但沒有任何工作。

有什麼想法?


編輯

經過進一步研究,我嘗試重新安裝埃宋與--enable-shared

$ cabal install aeson --enable-shared --reinstall 

同樣的問題。

回答

1

當您提供.o文件作爲GHC的輸入時,它不知道它們是否來自Haskell模塊。因此,它無法知道需要鏈接哪個Haskell依賴項。

您可以在鏈接命令行上手動指定依賴項(例如-package aeson),或者在鏈接命令行上提供原始的Haskell模塊哪種情況下GHC會自動確定依賴關係。