如何调用在Haskell中使用回调的C函数?
问题描述:
我正在尝试使用c2hs
从Haskell
调用以下C
函数。如何调用在Haskell中使用回调的C函数?
void rd_kafka_conf_set_rebalance_cb (
rd_kafka_conf_t *conf,
void (*rebalance_cb) (rd_kafka_t *rk,
rd_kafka_resp_err_t err,
rd_kafka_topic_partition_list_t *partitions,
void *opaque));
我不熟悉c2hs
,并且在声明绑定时遇到麻烦。
这是我已经试过:
--callback type
type RebalanceCbFun =
Ptr RdKafkaT -> CInt -> Ptr RdKafkaTopicPartitionListT -> Ptr Word8 -> IO()
foreign import ccall safe "wrapper"
mkRebalanceCallback :: RebalanceCbFun -> IO (FunPtr RebalanceCbFun)
foreign import ccall unsafe "rd_kafka.h &rd_kafka_conf_set_rebalance_cb"
rdKafkaConfSetRebalanceCb :: Ptr RdKafkaConfT -> FunPtr RebalanceCbFun -> IO()
不过,我有以下错误而编译此代码:
Unacceptable type in foreign declaration:
‘Ptr RdKafkaConfT
-> FunPtr
(Ptr RdKafkaT
-> Int32 -> Ptr RdKafkaTopicPartitionListT -> Ptr Word8 -> IO())
-> IO()’ cannot be marshalled in a foreign call
A foreign-imported address (via &foo) must have type (Ptr a) or (FunPtr a)
When checking declaration:
foreign import ccall unsafe "static rd_kafka.h &rd_kafka_conf_set_rebalance_cb" rdKafkaConfSetRebalanceCb
:: Ptr RdKafkaConfT -> FunPtr RebalanceCbFun -> IO()
我不明白是什么部分缺失Ptr
或FunPtr
这里。 我也试过整个rdKafkaConfSetRebalanceCb
包装成FunPtr
,如:
foreign import ccall unsafe "rd_kafka.h &rd_kafka_conf_set_rebalance_cb"
rdKafkaConfSetRebalanceCb :: FunPtr (Ptr RdKafkaConfT -> FunPtr RebalanceCbFun -> IO())
不知道它是有道理的,尽管它编译... 但我不知道如何使用这个功能,这就是我尝试(这是我想在结束了签名):
kafkaConfSetRebalanceCb :: RdKafkaConfTPtr -> RebalanceCbFun -> IO()
kafkaConfSetRebalanceCb conf cb = do
cb' <- mkRebalanceCallback cb
withForeignPtr conf $ \c -> rdKafkaConfSetRebalanceCb c cb'
return()
现在抱怨我没有要调用的函数,只是一个指针的函数(因为FunPtr
的包装)。
你能告诉我如何C
绑定可以正确完成上面的C
签名?
答
以下文件适合我(与ghc -c Test.hs
)编译。唯一真正的区别是我在国外进口中省略了&
。
{-# LANGUAGE ForeignFunctionInterface #-}
module Test where
import Data.Word
import Foreign.C.Types
import Foreign.Ptr
import Foreign.ForeignPtr
newtype RdKafkaT = RdKafkaT (Ptr RdKafkaT)
newtype RdKafkaConfT = RdKafkaConfT (Ptr RdKafkaConfT)
newtype RdKafkaTopicPartitionListT = RdKafkaTopicPartitionListT (Ptr RdKafkaTopicPartitionListT)
type RebalanceCbFun =
Ptr RdKafkaT -> CInt -> Ptr RdKafkaTopicPartitionListT -> Ptr Word8 -> IO()
foreign import ccall safe "wrapper"
mkRebalanceCallback :: RebalanceCbFun -> IO (FunPtr RebalanceCbFun)
foreign import ccall unsafe "rd_kafka.h rd_kafka_conf_set_rebalance_cb"
rdKafkaConfSetRebalanceCb :: Ptr RdKafkaConfT -> FunPtr RebalanceCbFun -> IO()
kafkaConfSetRebalanceCb :: ForeignPtr RdKafkaConfT -> RebalanceCbFun -> IO()
kafkaConfSetRebalanceCb conf cb = do
cb' <- mkRebalanceCallback cb
withForeignPtr conf $ \c -> rdKafkaConfSetRebalanceCb c cb'
+0
哇,的确!我甚至没有注意到它在那里!非常感谢你! –
未来访问者注意:C函数将会像这样调用Haskell代码,不能导入'unsafe'。 –