[Haskell-beginners] Improve my FFI code please...

Sean Charles sean at objitsu.com
Fri Jan 21 00:35:02 CET 2011


Hi list,

I am *still* cursing the fact that I like where Haskell is taking me but 
that I am too dumb to get it into my head as quickly as I'd like!
I will not give up and in that vein I have been beating myself up trying 
to run before I can walk as usual by attempting to write an FFI wrapper 
around the Ubuntu libcwiimote library!

Having been inspired by johnnylee.net and having found his code is for 
Windows and C# I have taken it on myself to reproduce what he's done but 
using Haskell and OpenGL. Laugh, I nearly cried because it's taken hours 
of frustration just to get this far! I've built the hardware and now I 
need the software as usual.

So, here we go... what I post here is the beginnings of a Wiimote 
wrapper. I *think* I understand Monads properly now, Brian Beck video on 
C9 (MSDN) really really helped a lot, I'd recommend that to anybody 
still struggling with the concept.

What I want to know is can my code be improved by using monadic chaining 
and if so, with what and how (LMAO) and also have I overlooked or 
otherwise not used the correct forms, idioms etc. to achieve what I have 
so far ? I am really keen to know how the real gurus out there could 
reduce this code down or make it 'more haskell like'.

Basically, I want you to correct it, improve it, show me and others how 
to do it right! I want it de-constructed, ripped to pieces, laughed at, 
openly mocked and I will learn from it and enjoy it because I am a 
developer! ;) LOL


It compiles with ...
     ghc --make -lcwiimote -o wmscan WiiMote.hs

and runs like so ...

    sean at sean-desktop:~/Documents/bluetooth$ ./wmscan 00:21:BD:A3:97:C7
    Connecting to 00:21:BD:A3:97:C7
    00:21:BD:A3:97:C7connected OK, disconnecting ...OK
    sean at sean-desktop:~/Documents/bluetooth$

...and I was proud as hell, almost as proud as watching my son born but 
without the goo.


Many thanks.
Sean

----

{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign
import Foreign.C.Types
import Foreign.Ptr
import Foreign.C.String
import System


#include "wiimote_api.h"


foreign import ccall unsafe "wiimote_api.h wiimote_open"
   c_wiimote_open :: CString -> IO (Ptr Word8)

foreign import ccall unsafe "wiimote_api.h wiimote_close"
   c_wiimote_close :: (Ptr Word8) -> IO CInt


wiiOpen :: String -> IO (Maybe (Ptr Word8))
wiiOpen wid = do
   handle <- withCString wid c_wiimote_open
   case handle of
     nullPtr -> return Nothing
     handle -> return (Just handle)


wiiClose :: Ptr Word8 -> IO Bool
wiiClose wptr = do
     response <- c_wiimote_close wptr
     case response of
         0 -> return True
         _ -> return False


-- Open the wiiremote, print the handle and close it
test :: String -> IO ()
test wiiHID = do
     wiimote <- wiiOpen wiiHID
     case  wiimote of
         Just handle -> do
             putStr (wiiHID ++ " connected OK, disconnecting ... ")
             status <- wiiClose handle
             case status of
                 True -> putStrLn "OK"
                 False -> putStrLn "FAIL"
         Nothing -> putStrLn "FAIL"
     return ()


-- expects a single HID string on the command line ...
main :: IO ()
main = do
     args <- getArgs
     case args of
         [hid] -> do
             putStrLn ("Connecting to " ++ hid)
             test hid
         _ -> putStrLn "Supply ONE Wiimote HID address!"





More information about the Beginners mailing list