首页 文章

使用GHCi测试FFI代码(带有“外部导入”)

提问于
浏览
10

每个人都很好(你当地时间) .

我在外部函数接口上经历了Real World Haskell's chapter,并做了一些后续阅读here . 我想对某些事情做一些澄清 .

以下是相当清楚的:

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

然后我可以加载我的绑定代码并测试,但......

_Question 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中加载它 . 这严重滞后于测试过程 .

_Question 2_如何在绑定到我的C代码的ghci中加载Haskell代码? FFI信息的主要来源都没有任何关于此的说法 . 无法摆弄 ghci -L 可以让它发挥作用 .

请感谢您提供的任何帮助 .

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
    

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

相关问题