好(你当地时间),每个人。
我在外部函数接口上查看了Real World Haskell's chapter, 并做了一些后续阅读here。我现在正在尝试绑定 对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
然后我可以加载我的绑定代码并测试,但是......
_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
可以让它发挥作用。
请感谢您提供的任何帮助。
答案 0 :(得分: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
在我的系统上,它也可以只使用库文件路径作为参数,但我不知道它是否可移植。