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;
} foo;

struct foo2 {
    int i1;
    int i2;
};

int fooFkt(foo f);

and then create a hsc file like:

import Foreign
import Foreign.C

#include "foo.h"

use hsc2hs:

{-# INCLUDE "foo.h" #-}
{-# LINE 1 "test.hsc" #-}
import Foreign
{-# LINE 2 "test.hsc" #-}
import Foreign.C


{-# LINE 5 "test.hsc" #-}

i dont understand it, i thought hat hsc2hs will import all needed things for me like the PI

who can give me a better example?

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
develhevel
  • 3,161
  • 4
  • 21
  • 27

2 Answers2

11

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.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
  • 2
    Doesn't bindings-dsl provide some float constant #defines? #fractional or something like that? – aleator May 19 '11 at 19:16
  • 2
    bindings-dsl gives you that and a whole bunch of other really useful stuff. I highly recommend it: https://bitbucket.org/mauricio/bindings-dsl/wiki/DetailedUsageGuide – sclv May 19 '11 at 19:41
2

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

tibbe
  • 8,809
  • 7
  • 36
  • 64