2013-03-28 10 views
8

良い(あなたの現地時間)、みんな。GHCiでFFIコードをテストする(外国からの輸入を伴う)

外国機能インターフェイスのReal World Haskell's chapter、 を経由し、フォローアップの読書hereを行った。私は現在、Cの関数に というバインディングを試しています。いくつかのことについていくつか説明したいと思います。

次はかなり明確である:

foreign import ccall unsafe "math.h sin" c_sin :: CDouble -> CDouble 

私はこれをロードし、GHCiの中でそれを使用するコード、およびすべてが正常であることができます。それは でさえ、emacsのHaskellモードで埋め込まれたghciに読み込まれます。私はテストのためにこれが素晴らしいことがわかります。 mathはシステムライブラリですので、これは簡単です。今

実世界ハスケルからの例:私は目的関数のシグネチャの残りの部分を残してきた

foreign import ccall unsafe "pcre.h pcre_compile" c_pcre_compile :: ... 

。今、私はこれをロードできません ハスケルモード。私はその後、私のバインディングコードとテストをロードすることができ

GHCi, version 7.6.2: 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 (dynamic) /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../lib/libpcre.so ... done 
final link ... done 

私は
ghci -lpcre 

を、そして物事が正しくロードされているインスタント確認を得る:私が見てきたすべての例では、これが行われなければならないと言います離れていても...

質問1_ pcreのようにghci内から非システムライブラリを読み込むことはできますか?これは 私がemacs内でテストできるようになります。

移動します。 私は自身のコードにバインディングを書き込もうとすると、もっと複雑になります。

foreign import ccall unsafe "myprint.h myprint" c_myprint :: CString -> IO() 

間違いなく無意味な機能です。私が実行して、これをコンパイルすることができました

{-# LANGUAGE ForeignFunctionInterface #-} 
-- printTest.hs 

import Foreign 
import Foreign.C.Types 
import Foreign.C.String 

import qualified Data.ByteString.Char8 as B 

--- 

foreign import ccall unsafe "myprint.h myprint" c_myprint :: CString -> IO() 

--- 

main = B.useAsCString (B.pack "Tempura is great!") c_myprint 

:C.ここで簡単なテストファイルであると、それはHaskellのから延ByteStringと 版画それを取る

ghc --make myprint.c printTest.hs 

と実行を得るが、私はghciでロードできませんでした。 これはテストプロセスに深刻な差があります。私は私の Cコードと結合するGHCiの中にHaskellコードをロードするためにしなければならない何

_Question 2_? FFI情報の主要な情報源はこれについて何も言及していませんでした。 ghci -Lで手品をすることはできません。

ご支援いただければ幸いです。

+2

Q2の場合、myprint.cをghciでロードしたい場合は、ライブラリとしてコンパイルする必要があります。これはcコンパイラ/ OS依存です。 – Jonke

+1

これらの行に沿って(gcc -c -fPIC foo.c -o foo.oとgcc -shared -Wl、-soname、libfoo.so.1 -o libfoo.so.1.0.1 foo.oなど)その – Jonke

答えて

9

ghciは、あなたのアーキテクチャに合っていれば、どんなライブラリでもロードでき、あるパスに置くことができます。ウィンドウ上で、問題の原因となっていたスペースを含むパス名は、私がまだそれをするかどうかわかりません。 GHCiの中で独自のコードをロードするために

、あなたが最初にそれの出力をロードするためにGHCiのを教えた後、それをコンパイルする必要があります。

mybox$ gcc -c myprint.c 
mybox$ ghci Myprint.hs myprint.o 

*Main> main 
Loading package array-0.4.0.1 ... linking ... done. 
Loading package deepseq-1.3.0.1 ... linking ... done. 
Loading package bytestring-0.10.0.2 ... linking ... done. 
Tempura is great! 
*Main> 

ます。また、ライブラリにCファイルをコンパイルしにそれを読み込むことができますghciですが、オブジェクトファイルを使用している1つのファイルに対しては非常に便利です。ライブラリを作成したい場合は、@ Jonkeのようなコマンドが動作するはずです。私のシステム(OSX)、私のシステムで

mybox$ gcc -shared -fPIC myprint.c -o libmyprint.dylib 
mybox$ ghci -L. -lmyprint Foo.hs 

で、それはまた、単に引数としてライブラリファイルパスを使用するように動作しますが、それはポータブルだ場合、私は知りません。

+0

'ghci myprint.o'これは最も簡単な方法です。ありがとうございました。 –

+0

myprint.oが相対ディレクトリ(例:lib/libx.a)に含まれる静的Cライブラリに依存する場合、どうすればよいですか? –

+1

@ThiadodeArrudaコンパイルしている場合と同様に、必要なリンカフラグを追加する必要があります。 '-Llib -lx -lmyprint'のようなものが動作するはずです。 Linkerフラグは順序付けに敏感なので、リンクするライブラリがたくさんある場合は、正しい順序付けを見つけるために少し作業する必要があります。 –

関連する問題