2

I am trying to bind to a C function from an external C library which returns a pointer to a memory buffer and the length of the buffer :

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

I tried the following code but got a segmentation fault as a result.

{-# 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'

I assume that peekArray did allocate enough memory, so I am not sure where it did go wrong. Any help welcome.

1 Answer 1

2

Stupid mistake, I missed a dereferencing step. This code now works :

{-# 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'
Sign up to request clarification or add additional context in comments.

2 Comments

If you want, you can simplify it noting thatcs <- blah ; return cs is equivalent to blah.
@ Chi. You are right, I did not sanitize completely before posting. I'll edit. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.