C 通过haskell传递void*

C 通过haskell传递void*,c,haskell,C,Haskell,我正在开发一个C库(),它使用haskell库(pandoc)来做一些工作。C库提供haskell包装回调来读取和写入数据。对于典型的回调,我还希望发送一个void*user_data,这样回调就不必依赖于全局变量 然而,在互联网上搜索时,我似乎不知道如何向Haskell传递void*变量 还有一个是char*(最终可以作为一种解决方法,但它不是很好)和一个从事物中生成指针的通用方法。然而,这些东西似乎不包括void(这也是可以理解的)。我看不出还有什么有用的 我的问题是,我可以使用什么类型将这

我正在开发一个C库(),它使用haskell库(pandoc)来做一些工作。C库提供haskell包装回调来读取和写入数据。对于典型的回调,我还希望发送一个
void*user_data
,这样回调就不必依赖于全局变量

然而,在互联网上搜索时,我似乎不知道如何向Haskell传递
void*
变量

还有一个是
char*
(最终可以作为一种解决方法,但它不是很好)和一个从事物中生成指针的通用方法。然而,这些东西似乎不包括
void
(这也是可以理解的)。我看不出还有什么有用的

我的问题是,我可以使用什么类型将这样的函数传递给Haskell

int func(char *buffer, void *user_data);

...

that_haskell_function(..., func, my_data);

我认为,任何指针类型都应该可以工作,但是
Ptr()
最有意义

{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign
import Numeric

foreign import ccall unsafe "foo"
    c_foo :: Ptr () -> IO ()

main :: IO ()
main =
    allocaBytes 8 $ \ptr -> do
        c_foo ptr
        x <- peek (castPtr ptr) :: IO Word64
        putStrLn (showHex x "")

+1-同意,我以前用这个来指使用FFI的泛型对象。毫无疑问,一个无人居住类型的Ptr(例如,
Void
——尽管命名只是一个证据)是一个更好的主意吗?您不会希望意外地取消对它的引用。在进行FFI绑定时,最好定义自己的无人居住类型,
data Foo
,然后使用
Ptr Foo
跟踪这些类型。@shachaf出于添加类型安全和自文档化代码的原因,我会这样做,但我看不出有人会意外地取消引用
Ptr()
-没有可存储的
实例()
。诚然,这是事实——尽管有人可以添加一个实例(但我不确定它会做什么…)。但是用一个有人居住的类型来表示一些永远不应该被取消引用的东西似乎很奇怪。@shachaf:但它实际上并不是无人居住的。Haskell实际上没有一个等价于
void*
(C也没有一个等价于
void
)的数据,尽管对于C函数
t func(void*)
,我们在所有v中都有等价的
。v->T
(如果您知道将要传递的类型,原则上可以使用
unsecfect
),因此我认为
void*
将等同于
ImpredicativeTypes
type
Ptr(对于所有a.a)
。这太荒谬了。我想说
Ptr()
很好。
#include <string.h>

void foo(void *ptr)
{
    memset(ptr, 0xEB, 8);
}
ebebebebebebebeb