How to use hsc2hs to bind to constants, functions and data structures?

前端 未结 2 758
遥遥无期
遥遥无期 2020-12-15 11:10

i need a example how to use hsc2hs, i thought that when i write a header file like:

// foo.h
#define PI 3.14159

typedef struct {
    int i1;
    int i2;
} f         


        
相关标签:
2条回答
  • 2020-12-15 11:32

    Following RWH ch 17, you need to introduce something that binds the C PI value to a symbol in Haskell.

    For example:

    {-# LANGUAGE ForeignFunctionInterface #-}
    {-# LANGUAGE CPP                      #-}
    
    import Foreign
    import Foreign.C
    
    -- helpers
    import Control.Applicative
    import Control.Monad
    
    #include "foo.h"
    
    -- binding a symbol
    
    -- Note that hsc2hs can't marshal floating point CPP values, so this will be "3"
    -- c_pi :: CInt
    -- c_pi = #const PI
    
    -- Instead, bind to a function that returns a CFloat
    pi' :: Float
    pi' = realToFrac c_pi
    
    foreign import ccall unsafe "my_pi" c_pi :: CFloat
    

    And while we're here, we can also marshal the struct to and from Haskell:

    -- Marshalling for the struct foo
    
    data Foo = Foo { i1, i2 :: Int }
        deriving Show
    
    -- Define how to marshal foo structs
    
    instance Storable Foo where
        sizeOf    _ = #{size foo}
    
        alignment _ = alignment (undefined :: CInt)
    
        poke p foo  = do
            #{poke foo, i1} p $ i1 foo
            #{poke foo, i2} p $ i2 foo
    
        peek p = return Foo
                  `ap` (#{peek foo, i1} p)
                  `ap` (#{peek foo, i2} p)
    

    And bind to fooFkt function:

    -- Import the function too
    
    foreign import ccall "foo.h fooFkt"
        c_fooFkt :: Ptr Foo -> IO CInt
    
    -- Marshal data to and from C
    
    fooFkt :: Foo -> IO Int
    fooFkt f = fromIntegral <$> with f c_fooFkt
    

    Done.

    0 讨论(0)
  • 2020-12-15 11:39

    It works if you actually use some definitions from foo.h:

    import Foreign
    import Foreign.C
    
    #include "foo.h"
    
    pi = #const PI
    

    gives

    {-# INCLUDE "foo.h" #-}
    {-# LINE 1 "test.hsc" #-}
    import Foreign
    {-# LINE 2 "test.hsc" #-}
    import Foreign.C
    
    
    {-# LINE 5 "test.hsc" #-}
    
    pi = 3
    {-# LINE 7 "test.hsc" #-}
    

    Here's a real world usage example from the network package: https://github.com/haskell/network/blob/master/Network/Socket/ByteString/MsgHdr.hsc

    0 讨论(0)
提交回复
热议问题