Search code examples
haskellc2hs

C2HS marshalling double pointer


When there is a function like:

some_type_t* some_type_create(const char* name, char** errptr);

is there a way to get C2HS to generate a Haskell binding with the following signature?

someTypeCreate :: String -> IO (SomeTypeFPtr, String)

Here is what I can get so far:

{#fun some_type_create as ^ 
    {`String', alloca- `Ptr CChar' peek*} -> `SomeTypeFPtr' #}

and it works in a way that I get

someTypeCreate :: String -> IO (SomeTypeFPtr, (Ptr CChar))

but how do I make it return IO (SomeTypeFPtr, String)
(or better IO (Either String SomeTypeFPtr)) since String represents the error)?

I assume that I should use/write a different marshaller to use instead of peek which would convert the result type but I don't quite understand how to do it.


Solution

  • I think I've figured it out, I just wrote the following marshallers:

    nullableM :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
    nullableM f ptr = if ptr == nullPtr
        then return Nothing
        else liftM Just $ f ptr
    {-# INLINE nullableM #-}
    
    toStringMaybe :: CString -> IO (Maybe String)
    toStringMaybe = nullableM peekCString 
    {-# INLINE toStringMaybe #-}
    
    peekStringMaybe :: Ptr CString -> IO (Maybe String)
    peekStringMaybe x = peek x >>= toStringMaybe
    {-# INLINE peekStringMaybe #-}