我需要一个例子如何使用hsc2hs,我想当我写一个头文件时:
// foo.h
#define PI 3.14159
typedef struct {
int i1;
int i2;
} foo;
struct foo2 {
int i1;
int i2;
};
int fooFkt(foo f);
然后创建一个hsc文件,如:
import Foreign
import Foreign.C
#include "foo.h"
使用hsc2hs
:
{-# INCLUDE "foo.h" #-}
{-# LINE 1 "test.hsc" #-}
import Foreign
{-# LINE 2 "test.hsc" #-}
import Foreign.C
{-# LINE 5 "test.hsc" #-}
我不明白,我认为帽子hsc2hs将为我导入所有需要的东西,如PI
谁可以给我一个更好的例子?
答案 0 :(得分:9)
在RWH ch 17之后,您需要引入一些将C PI
值绑定到Haskell中的符号的内容。
例如:
{-# 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
虽然我们在这里,但我们也可以将结构编组到Haskell和来自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)
并绑定到fooFkt
函数:
-- 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
完成。
答案 1 :(得分:2)
如果你实际使用foo.h
中的一些定义:
import Foreign
import Foreign.C
#include "foo.h"
pi = #const PI
给出
{-# 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" #-}
以下是网络包中的实际使用示例:https://github.com/haskell/network/blob/master/Network/Socket/ByteString/MsgHdr.hsc