用GHCi测试FFI代码(带有“外部输入”) [英] Testing FFI Code (with "foreign import"s) with GHCi

查看:123
本文介绍了用GHCi测试FFI代码(带有“外部输入”)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好(你当地的时间),每个人。

我经历了真实世界Haskell关于外部函数接口的章节,
并做了一些后续的阅读
这里。我现在正在尝试将
绑定到C函数,并且我想要澄清一些事情。



以下内容非常清晰:

  foreign import ccall unsafemath.h sinc_sin :: CDouble  - > CDouble 

我可以加载这个和使用ghci的代码,并且一切正常。甚至
在emacs的Haskell模式下加载嵌入的ghci。我觉得这非常适合测试。
math 是一个系统库,所以这很简单。



现在来自Real World Haskell:

  foreign import ccall unsafepcre.h pcre_compilec_pcre_compile :: ... 

我故意遗漏了函数签名的其余部分。现在,我无法加载
Haskell模式。我见过的所有例子都说这个必须完成:

  ghci -lpcre 



 

> GHCi,版本7.6.2:http://www.haskell.org/ghc/:?寻求帮助
加载包ghc-prim ...链接...完成。
加载包integer-gmp ...链接...完成。
加载程序包库...链接...完成。
加载对象(动态)/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../lib/libpcre.so ... done
final link ... done

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



_Question 1 _ 我可以从ghci中加载非系统库,例如pcre吗?这将
允许我在emacs中测试。



继续。
当我尝试向我的自己的 C代码写入绑定时,情况会变得更加复杂。

 国外进口ccall不安全myprint.h myprintc_myprint :: CString  - > IO()

肯定是一个毫无意义的函数。它需要一个Haskell的ByteString,
用C打印出来。这里有一个简单的测试文件:

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

导入外部
导入Foreign.C.Types
导入Foreign.C.String

导入合格的Data.ByteString.Char8为B

---

外部导入ccall不安全myprint.h myprintc_myprint :: CString - > IO()

---

main = B.useAsCString(B.packTempura is great!)c_myprint



我已经可以通过这样做来编译它:

  ghc --make myprint.c printTest.hs 

获得一个可执行文件,但我没有'根本不能用ghci加载它。
这严重滞后于测试过程。



_Question 2 _ 我必须做什么来加载ghci中的Haskell代码, 我的 C代码?
FFI信息的主要来源没有任何关于此的说法。
ghci -L 可以让它起作用。



你可以提供任何帮助。

解决方案

ghci将加载任何库,只要它对您的架构有效并且可以位于某些路径。在windows中,包含用于导致问题的空格的路径名,我不知道它们是否仍然存在。



要在ghci中加载自己的代码,您需要先编译它,然后告诉ghci加载输出:

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

* Main> main
加载程序包array-0.4.0.1 ...链接...完成。
加载包deepseq-1.3.0.1 ...链接...完成。
加载包bytestring-0.10.0.2 ...链接...完成。
天妇罗很棒!
* Main>

你也可以将C文件编译成一个库并加载到ghci中,但是只需要一个文件使用目标文件非常方便。如果你想创建一个库,像@Jonke建议的命令应该工作。在我的系统(OSX)上,

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

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


Good (your local time of day), everyone.

I went through Real World Haskell's chapter on the Foreign Function Interface, and did some follow-up reading here. I'm now experimenting with binding to C functions, and I'd like some clarification on some things.

The following is fairly clear:

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

I can load this and code that uses it in ghci, and everything is fine. It even loads in the embedded ghci in emacs's Haskell mode. I find this great for testing. math is a system library so this is straight-forward.

Now an example from Real World Haskell:

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

I've left out the rest of the function signature on purpose. Now, I can't load this in Haskell mode. All the examples I've seen say this must be done:

ghci -lpcre

Which I do, and get instant confirmation that things are loading properly:

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

I can then load my binding code and test away, but...

_Question 1_ Can I load non-system libraries from within ghci, like pcre? This would allow me to test within emacs.

Moving on. Things get more complicated when I try to write bindings to my own C code.

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

Admittedly a rather pointless function. It takes a ByteString from Haskell and prints it with C. Here is a simple test file:

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

I have been able to compile this by doing:

ghc --make myprint.c printTest.hs

And get an executable, but I haven't been able to load it in ghci at all. This severely lags the testing process.

_Question 2_ What do I have to do to load Haskell code in ghci that binds to my C code? None of the major sources of FFI information had anything to say about this. No amount of fiddling with ghci -L could get it to work.

Please and thanks for any help you can offer.

解决方案

ghci will load any library so long as it's valid for your architecture and can be located on some path. On windows, pathnames with spaces used to cause problems, I don't know if they still do.

To load your own code in ghci, you need to first compile it, then tell ghci to load the output of that:

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>

You could also compile the C files into a library and load that into ghci, but for just one file using an object file is quite convenient. If you want to create a library, a command like @Jonke suggested should work. On my system (OSX),

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

On my system it also works to just use the library filepath as an argument, but I don't know if that's portable.

这篇关于用GHCi测试FFI代码(带有“外部输入”)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆