通过haskell传递void*

Sha*_*baz 17 c haskell

我正在使用一个使用haskell库(pandoc)来完成一些工作的C库(libpandoc).C库为haskell包装器回调提供读写数据.典型的回调,我也想发送一个,void *user_data以便回调不必依赖于全局变量.

然而,在互联网上搜索,我似乎无法弄清楚如何将Haskell传递给void *变量.

还有就是CString的是一个char *(并最终被用来作为一种解决方法,但它不是那么好)和普通PTR这使得指针出来的东西.但是,这些东西似乎不包括void(这也是可以理解的).看看Foreign.C我没有看到任何有用的东西.

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

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

...

that_haskell_function(..., func, my_data);
Run Code Online (Sandbox Code Playgroud)

Tho*_*son 20

我认为任何指针类型都应该起作用,但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 "")
Run Code Online (Sandbox Code Playgroud)

和C文件:

#include <string.h>

void foo(void *ptr)
{
    memset(ptr, 0xEB, 8);
}
Run Code Online (Sandbox Code Playgroud)

给出结果:

ebebebebebebebeb
Run Code Online (Sandbox Code Playgroud)

  • 当然,无人居住的Ptr(例如,"Void" - 虽然命名只是一种共识)是一个更好的主意吗?你不会想要意外地取消引用它.在进行FFI绑定时,最好定义自己的无人居住类型`data Foo`,然后使用`Ptr Foo`来跟踪类型. (6认同)
  • @shachaf为了增加类型安全性和自我记录代码的原因我会这样做,但是我不认为你认为有人会不小心取消引用`Ptr()` - 没有`实例Storable()`. (3认同)
  • 诚然,这是真的 - 虽然有人可以添加一个(但我不确定它会做什么......).但是使用有人居住的类型从来不应该被解除引用只是看起来很奇怪. (3认同)