11

いいですね(あなたの現地時間)、皆さん。

私はReal World Haskell の外部関数インターフェイスに関する章を読み、ここでいくつかのフォローアップを読みました。私は現在、C 関数へのバインディングを試していますが、いくつかの点について明確にしたいと思います。

次のことはかなり明確です。

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

これとそれを使用するコードをghciでロードでき、すべて問題ありません。emacs の Haskell モードでは、組み込みの ghci にもロードされます。これはテストに最適だと思います。 mathはシステム ライブラリなので、これは簡単です。

実世界の Haskell からの例:

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

関数シグネチャの残りの部分は意図的に省略しました。これを Haskell モードでロードすることはできません。私が見たすべての例は、これを行う必要があると言っています:

ghci -lpcre

私はこれを行い、物事が適切にロードされていることを即座に確認します:

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

その後、バインディング コードを読み込んでテストできますが...

_質問 1_ pcre のように、システム以外のライブラリを ghci 内からロードできますか? これにより、emacs 内でテストできるようになります。

先に進みます。自分のC コードにバインドを記述しようとすると、事態はさらに複雑になります。

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

確かにかなり無意味な機能です。Haskell から ByteString を取得し、C で出力します。簡単なテスト ファイルを次に示します。

{-# 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

私はこれをコンパイルすることができました:

ghc --make myprint.c printTest.hs

実行可能ファイルを取得しますが、ghci にまったくロードできませんでした。これにより、テストプロセスが大幅に遅れます。

_質問 2_私のC コードにバインドするghciに Haskell コードをロードするには、どうすればよいですか? FFI情報の主要な情報源のどれも、これについて何も言いませんでした. どれだけいじってghci -Lも、それを機能させることはできませんでした。

あなたが提供できるどんな助けにも感謝します。

4

1 に答える 1

11

ghci は、アーキテクチャに有効で、何らかのパスに配置できる限り、任意のライブラリをロードします。Windows では、スペースを含むパス名が問題を引き起こしていましたが、今でも問題があるかどうかはわかりません。

独自のコードを 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

私のシステムでは、ライブラリのファイルパスを引数として使用することもできますが、それが移植可能かどうかはわかりません。

于 2013-03-28T10:17:09.887 に答える