11

大家好(您的当地时间)。

我浏览了Real World Haskell 关于外部函数接口的章节,并在此处进行了一些后续阅读。我现在正在尝试绑定到 C 函数,我想澄清一些事情。

以下是相当清楚的:

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

我可以加载这个和在 ghci 中使用它的代码,一切都很好。它甚至以 emacs 的 Haskell 模式加载到嵌入式 ghci 中。我发现这非常适合测试。 math是一个系统库,所以这很简单。

现在是 Real World 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_我可以从 ghci 中加载非系统库,比如 pcre 吗?这将允许我在 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 中,但是对于仅一个文件,使用目标文件非常方便。如果你想创建一个库,像@Jonke 建议的命令应该可以工作。在我的系统(OSX)上,

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

在我的系统上,它也可以仅使用库文件路径作为参数,但我不知道这是否可移植。

于 2013-03-28T10:17:09.887 回答