【发布时间】:2013-03-04 14:28:59
【问题描述】:
'C'wiringPi 库中有一个函数类型,
extern void (*pinMode) (int pin, int mode) ;
我尝试使用带有 FunPtr 的 FFI 从 haskell 调用它。所以我做到了,
foreign import ccall unsafe "wiringPi.h &pinMode" c_pinMode
:: FunPtr (CInt -> CInt -> IO ())
foreign import ccall "dynamic" dc_pinMode
:: FunPtr (CInt -> CInt -> IO ()) -> (CInt -> CInt -> IO ())
但由于某种原因,即使它可以编译,它似乎也没有调用 'pinMode' 指向的函数。
所以我尝试使用普通的 Foreign.Ptr,我想我可以偷看 Ptr 以获取对“pinMode”指向的底层“C”函数的引用。所以我尝试了,
foreign import ccall "wiringPi.h &pinMode" c_pinMode
:: Ptr (Ptr (CInt -> CInt -> IO ()))
然后,在调用 'pinMode' 的 haskell 函数的实现中,我使用 peek 两次来获取对底层函数的引用。但是我不断收到编译错误,编译器告诉我(CInt -> CInt -> IO ()) 类型的函数不是“可存储”类型类的实例。
所以我检查了可存储类型类,以使 (CInt -> CInt -> IO ()) 成为可存储类型类的实例。所需的最低实现是 peek、poke 和其他一些功能。我意识到,它真的不应该这样很难调用被指针引用的函数..
我觉得我缺少一些基本的东西。有人可以指出我正确的方向吗?
感谢和问候
【问题讨论】:
-
extern void (*pinMode) (int pin, int mode);将pinMode声明为一个指针,指向一个接受两个ints 并返回void的函数。试试foreign import ccall unsafe "wiringPi.h pinMode" c_pinMode,获取指针的地址会给你太多的间接层级(但我对 FFI 不太熟悉,所以我不能 100% 确定我的解释是正确的)。 -
pinMode是函数还是函数指针?如果是函数指针,我觉得foreign import ccall unsafe "wiringPi.h &pinMode" c_pinMode的类型应该是Ptr (FunPtr (CInt -> CInt -> IO ()))。 -
@nymk pinMode 是一个指向以 2 个整数作为参数的过程的指针。说,我将导入的类型重写为您提到的内容。是否仍然可以在 haskell 端获得对底层函数的引用?因为,如果 c_pinMode 的类型是
Ptr (FunPtr (CInt -> CInt -> IO ())),我不能做c_pinMode (3 :: CInt) (4 :: CInt)。我认为这行不通。不过我会试试你说的。