具有双指针参数的Haskell FFI问题

时间:2015-12-29 08:33:59

标签: c haskell ffi

我正在尝试从外部C库绑定到C函数,该库返回指向内存缓冲区的指针和缓冲区的长度:

extern int myfunc(int arg1, unsigned char **buffer, size_t *buffer_len);

我尝试了以下代码但结果出现了分段错误。

{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign
import Foreign.C.Types (CInt(..), CUChar(..), CSize(..))
import Foreign.Ptr (Ptr)
import Foreign.Marshal.Array (peekArray)

foreign import ccall unsafe "myfunc" c_myfunc :: CInt -> Ptr (Ptr CUChar) -> Ptr CSize -> IO (CInt)

getBuffer :: Int -> IO [CUChar]
getBuffer arg1 = do
    alloca $ \buffer -> do
        alloca $ \buflen -> do
            res <- c_myfunc (CInt arg1) buffer buflen

            buflen' <- fromIntegral <$> peek buflen

            cs  <- peekArray buflen' buffer  -- return a [Ptr CUChar] of size buflen
            cs' <- mapM peek cs  -- return a [CUChar] of size buflen

            return cs'

我认为peekArray确实分配了足够的内存,所以我不确定它出错的地方。欢迎任何帮助。

1 个答案:

答案 0 :(得分:1)

愚蠢的错误,我错过了一个解除引用的步骤。此代码现在有效:

{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign
import Foreign.C.Types (CInt(..), CUChar(..), CSize(..))
import Foreign.Ptr (Ptr)
import Foreign.Marshal.Array (peekArray)

foreign import ccall unsafe "myfunc" c_myfunc :: CInt -> Ptr (Ptr CUChar) -> Ptr CSize -> IO (CInt)

getBuffer :: Int -> IO [CUChar]
getBuffer arg1 = do
    alloca $ \ ptrbuf -> do
        alloca $ \buflen -> do
            res <- c_myfunc (CInt arg1) ptrBuf buflen

            buflen' <- fromIntegral <$> peek buflen

            buffer  <- peek ptrBuf    -- I MISSED THIS ONE. Extra dereferencing needed.
            peekArray buflen' buffer  -- return a [CUChar] of size buflen'