diff --git a/Language/C/Inline/ObjC.hs b/Language/C/Inline/ObjC.hs
--- a/Language/C/Inline/ObjC.hs
+++ b/Language/C/Inline/ObjC.hs
@@ -12,6 +12,11 @@
 -- This module exports the principal API for inline Objective-C.
 
 module Language.C.Inline.ObjC (
+
+  -- * Re-export types from 'Foreign.C'
+  module Foreign.C.Types, CString, CStringLen, CWString, CWStringLen, Errno,
+
+  -- * Combinators for inline Objective-C 
   objc_import, objc_interface, objc_implementation, objc, objc_emit
 ) where
 
@@ -24,6 +29,7 @@
 import Data.List
 import Foreign.C                  as C
 import Foreign.C.String           as C
+import Foreign.C.Types
 import Foreign.Marshal            as C
 import Language.Haskell.TH        as TH
 import Language.Haskell.TH.Syntax as TH
@@ -91,7 +97,7 @@
     exportVar var
       = do
         {   -- Determine the argument and result types of the exported Haskell function
-        ; (argTys, inIO, resTy) <- splitHaskellType <$> determineVarType var
+        ; (tvs, argTys, inIO, resTy) <- splitHaskellType <$> determineVarType var
 
             -- Determine C types
         ; cArgTys <- mapM (haskellTypeToCType ObjC) argTys
@@ -103,7 +109,7 @@
         ; (bridgeResTy,  cBridgeResTy,  hsResMarshaller,  cResMarshaller)  <- generateHaskellToCMarshaller resTy cResTy
 
             -- Haskell type of the foreign wrapper function
-        ; let hsWrapperTy = haskellWrapperType bridgeArgTys bridgeResTy
+        ; let hsWrapperTy = haskellWrapperType tvs bridgeArgTys bridgeResTy
 
             -- Generate the Haskell wrapper
         ; let cwrapperName = mkName . nameBase $ var
@@ -133,17 +139,31 @@
               $ty:cBridgeResTy $id:(show hswrapperName) ($params:(cParams cBridgeArgTys cArgVars));
             |]
             ++
-            wrapperDef
+            map makeStaticFunc wrapperDef
         }
 
-    splitHaskellType (ArrowT `AppT` arg `AppT` res)
-      = let (args, inIO, res') = splitHaskellType res
+    splitHaskellType (ForallT tvs _ctxt ty)                   -- collect quantified variables (drop the context)
+      = let (tvs', args, inIO, res) = splitHaskellType ty
         in
-        (arg:args, inIO, res')
-    splitHaskellType (ConT io `AppT` res) | io == ''IO
-      = ([], True, res)
+        (tvs ++ tvs', args, inIO, res)
+    splitHaskellType (ArrowT `AppT` arg `AppT` res)           -- collect argument types
+      = let (tvs, args, inIO, res') = splitHaskellType res
+        in
+        (tvs, arg:args, inIO, res')
+    splitHaskellType (ConT io `AppT` res) | io == ''IO        -- is it an 'IO' function?
+      = ([], [], True, res)
     splitHaskellType res
-      = ([], False, res)
+      = ([], [], False, res)
+    
+    makeStaticFunc (FuncDef (Func    dspec f decl ps    body loc1) loc2)
+      = FuncDef (Func    (addStatic dspec) f decl ps    body loc1) loc2
+    makeStaticFunc (FuncDef (OldFunc dspec f decl ps ig body loc1) loc2)
+      = FuncDef (OldFunc (addStatic dspec) f decl ps ig body loc1) loc2
+    makeStaticFunc def = def
+    
+    addStatic (DeclSpec         st tqs ts loc) = DeclSpec         (Tstatic loc:st) tqs ts loc
+    addStatic (AntiTypeDeclSpec st tqs ts loc) = AntiTypeDeclSpec (Tstatic loc:st) tqs ts loc
+    addStatic declSpec                         = declSpec
 
 forExpD :: Callconv -> String -> Name -> TypeQ -> DecQ
 forExpD cc str n ty
@@ -176,7 +196,7 @@
         generateCToHaskellMarshaller (ConT resTy) cResTy
 
         -- Haskell type of the foreign wrapper function
-    ; let hsWrapperTy = haskellWrapperType bridgeArgTys bridgeResTy
+    ; let hsWrapperTy = haskellWrapperType [] bridgeArgTys bridgeResTy
 
         -- FFI setup for the C wrapper
     ; cwrapperName <- newName "cwrapper"
@@ -208,12 +228,16 @@
 
 -- Turn a list of argument types and a result type into a Haskell wrapper signature.
 --
--- > haskellWrapperType [a1, .., an] r = [| a1 -> .. -> an -> IO r |]
+-- > haskellWrapperType [tv1, .., tvm] [a1, .., an] r = [| forall tv1 .. tvm. a1 -> .. -> an -> IO r |]
 --
-haskellWrapperType :: [TH.TypeQ] -> TH.TypeQ -> TH.TypeQ
-haskellWrapperType []             resTy = [t| IO $resTy |]
-haskellWrapperType (argTy:argTys) resTy = [t| $argTy -> $(haskellWrapperType argTys resTy) |]
+haskellWrapperType :: [TH.TyVarBndr] -> [TH.TypeQ] -> TH.TypeQ -> TH.TypeQ
+haskellWrapperType []  argTys resTy = wrapperBodyType argTys resTy                          -- monotype
+haskellWrapperType tvs argTys resTy = forallT tvs (cxt []) (wrapperBodyType argTys resTy)   -- polytype
 
+wrapperBodyType :: [TH.TypeQ] -> TH.TypeQ -> TH.TypeQ
+wrapperBodyType []             resTy = [t| IO $resTy |]
+wrapperBodyType (argTy:argTys) resTy = [t| $argTy -> $(wrapperBodyType argTys resTy) |]
+
 -- Generate the prototype of and function definition of a C marshalling wrapper.
 --
 -- Given a C expression to be executed, this generator produces a C function that executes the expression with all
@@ -297,7 +321,7 @@
         ; appendFile objcFname_h (unlines (map mkImport headers) ++ "\n")
         ; appendFile objcFname_h (show $ QC.ppr objc_h)
         ; writeFile  objcFname_m (info origFname)
-        ; appendFile objcFname_m ("#import \"" ++ objcFname_h ++ "\"\n\n")
+        ; appendFile objcFname_m ("#import \"" ++ takeFileName objcFname_h ++ "\"\n\n")
         ; appendFile objcFname_m (show $ QC.ppr objc_m)
         }
     ; objc_jumptable <- getForeignTable
diff --git a/Language/C/Inline/ObjC/Marshal.hs b/Language/C/Inline/ObjC/Marshal.hs
--- a/Language/C/Inline/ObjC/Marshal.hs
+++ b/Language/C/Inline/ObjC/Marshal.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
+{-# LANGUAGE PatternGuards, TemplateHaskell, QuasiQuotes #-}
 
 -- |
 -- Module      : Language.C.Inline.ObjC.Marshal
@@ -28,9 +28,12 @@
 ) where
 
   -- common libraries
+import Data.Map                   as Map
+import Data.Word
 import Foreign.C                  as C
 import Foreign.C.String           as C
 import Foreign.Marshal            as C
+import Foreign.Ptr                as C
 import Foreign.StablePtr          as C
 import Language.Haskell.TH        as TH
 import Language.Haskell.TH.Syntax as TH
@@ -47,7 +50,7 @@
 -- Auxilliary functions
 -- --------------------
 
--- Check that the given TH name is that of a Haskell variable and determine its type.
+-- |Check that the given TH name is that of a Haskell variable and determine its type.
 --
 determineVarType :: TH.Name -> Q TH.Type
 determineVarType vname
@@ -63,7 +66,7 @@
           }
     }
 
--- Check that the given TH name is that of a Haskell type constructor.
+-- |Check that the given TH name is that of a Haskell type constructor.
 --
 checkTypeName :: TH.Name -> Q ()
 checkTypeName tyname
@@ -85,46 +88,112 @@
 -- Determine foreign types
 -- -----------------------
 
--- Determine the C type that we map a given Haskell type to.
+-- |Determine the C type that we map a given Haskell type to.
 --
 haskellTypeToCType :: QC.Extensions -> TH.Type -> Q QC.Type
-haskellTypeToCType lang (ListT `AppT` (ConT char))
+haskellTypeToCType lang (ForallT _tvs _ctxt ty)           -- ignore quantifiers and contexts
+  = haskellTypeToCType lang ty
+haskellTypeToCType lang (ListT `AppT` (ConT char))        -- marshal '[Char]' as 'String'
   | char == ''Char 
   = haskellTypeNameToCType lang ''String
-haskellTypeToCType lang (ConT tc)
+haskellTypeToCType lang ty@(ConT maybeC `AppT` argTy)     -- encode a 'Maybe' around a pointer type in the pointer
+  | maybeC == ''Maybe
+  = do
+    { cargTy <- haskellTypeToCType lang argTy
+    ; if isCPtrType cargTy
+      then
+        return cargTy
+      else
+        unknownType lang ty
+    }
+haskellTypeToCType lang (ConT tc)                         -- nullary type constructors are delegated
   = haskellTypeNameToCType lang tc
-haskellTypeToCType _lang ty
+haskellTypeToCType lang ty@(VarT tv)                      -- can't marshal an unknown type
+  = unknownType lang ty
+haskellTypeToCType lang ty@(UnboxedTupleT _)              -- there is nothing like unboxed tuples in C
+  = unknownType lang ty
+haskellTypeToCType _lang ty                               -- everything else is marshalled as a stable pointer
   = return [cty| typename HsStablePtr |]
 
--- Determine the C type that we map a given Haskell type constructor to — i.e., we map all Haskell
--- whose outermost constructor is the given type constructor to the returned C type..
+unknownType lang ty = reportErrorAndFail lang $ "don't know a foreign type suitable for Haskell type '" ++ TH.pprint ty ++ "'"
+
+-- |Determine the C type that we map a given Haskell type constructor to — i.e., we map all Haskell types
+-- whose outermost constructor is the given type constructor to the returned C type.
 --
+-- All types representing boxed values that are not explicitly mapped to a specific C type, are mapped to
+-- stable pointers.
+--
 haskellTypeNameToCType :: QC.Extensions -> TH.Name -> Q QC.Type
-haskellTypeNameToCType ObjC tyname
-  | tyname == ''String = return [cty| typename NSString * |]
-  | tyname == ''()     = return [cty| void |]
-haskellTypeNameToCType _lang tyname
-  = return [cty| typename HsStablePtr |]
+haskellTypeNameToCType ext tyname
+  = case Map.lookup tyname (haskellToCTypeMap ext) of
+      Just cty -> return cty
+      Nothing  -> do
+        { info <- reify tyname
+        ; case info of
+            PrimTyConI _ _ True -> unknownUnboxedType
+            _                   -> return [cty| typename HsStablePtr |]
+        }
+  where
+    unknownUnboxedType = reportErrorAndFail ext $ 
+                           "don't know a foreign type suitable for the unboxed Haskell type '" ++ show tyname ++ "'"  
 
+haskellToCTypeMap :: QC.Extensions -> Map TH.Name QC.Type
+haskellToCTypeMap ObjC
+  = Map.fromList
+    [ (''CChar,   [cty| char |])
+    , (''CSChar,  [cty| signed char |])
+    , (''CUChar,  [cty| unsigned char |])
+    , (''CShort,  [cty| short |])
+    , (''CUShort, [cty| unsigned short |])
+    , (''Int,     [cty| int |])
+    , (''CInt,    [cty| int |])
+    , (''Word,    [cty| unsigned int |])
+    , (''CUInt,   [cty| unsigned int |])
+    , (''CLong,   [cty| long |])
+    , (''CULong,  [cty| unsigned long |])
+    , (''CLLong,  [cty| long long |])
+    , (''CULLong, [cty| unsigned long long |])
+    --
+    , (''Float,   [cty| float |])
+    , (''CFloat,  [cty| float |])
+    , (''Double,  [cty| double |])
+    , (''CDouble, [cty| double |])
+    --
+    , (''String,  [cty| typename NSString * |])
+    , (''(),      [cty| void |])
+    ]
+haskellToCTypeMap _lang
+  = Map.empty
 
+-- Check whether the given C type is an overt pointer.
+--
+isCPtrType :: QC.Type -> Bool
+isCPtrType (Type _ (Ptr {}) _)           = True
+isCPtrType (Type _ (BlockPtr {}) _)      = True
+isCPtrType (Type _ (Array {}) _)         = True
+isCPtrType ty
+  | ty == [cty| typename HsStablePtr |]  = True
+  | otherwise                            = False
+
+
 -- Determine marshallers and their bridging types
 -- ----------------------------------------------
 
--- Constructs Haskell code to marshal a value (used to marshal arguments and results).
+-- |Constructs Haskell code to marshal a value (used to marshal arguments and results).
 --
 -- * The first argument is the code referring to the value to be marshalled.
 -- * The second argument is the continuation that gets the marshalled value as an argument.
 --
 type HaskellMarshaller = TH.ExpQ -> TH.ExpQ -> TH.ExpQ
 
--- Constructs C code to marshal an argument (used to marshal arguments and results).
+-- |Constructs C code to marshal an argument (used to marshal arguments and results).
 --
 -- * The argument is the identifier of the value to be marshalled.
 -- * The result of the generated expression is the marshalled value.
 --
 type CMarshaller = TH.Name -> QC.Exp
 
--- Generate the type-specific marshalling code for Haskell to C land marshalling for a Haskell-C type pair.
+-- |Generate the type-specific marshalling code for Haskell to C land marshalling for a Haskell-C type pair.
 --
 -- The result has the following components:
 --
@@ -134,7 +203,44 @@
 -- * Generator for the C-side marshalling code.
 --
 generateHaskellToCMarshaller :: TH.Type -> QC.Type -> Q (TH.TypeQ, QC.Type, HaskellMarshaller, CMarshaller)
+generateHaskellToCMarshaller hsTy@(ConT maybe `AppT` argTy) cTy
+  | maybe == ''Maybe && isCPtrType cTy
+  = do 
+    { (argTy', cTy', hsMarsh, cMarsh) <- generateHaskellToCMarshaller argTy cTy
+    ; ty <- argTy'
+    ; case ty of
+        ConT ptr `AppT` _ 
+          | ptr == ''C.Ptr       -> return ( argTy'
+                                           , cTy'
+                                           , \val cont -> [| case $val of
+                                                               Nothing   -> $cont C.nullPtr
+                                                               Just val' -> $(hsMarsh [|val'|] cont) |] 
+                                           , cMarsh
+                                           )
+          | ptr == ''C.StablePtr -> return ( argTy'
+                                           , cTy'
+                                           , \val cont -> [| case $val of
+                                                               Nothing   -> $cont (C.castPtrToStablePtr C.nullPtr)
+                                                               Just val' -> $(hsMarsh [|val'|] cont) |]
+                                                               -- NB: the above cast works for GHC, but is in the grey area
+                                                               --     of the FFI spec
+                                           , cMarsh
+                                           )
+        _ -> reportErrorAndFail ObjC $ "missing 'Maybe' marshalling for '" ++ prettyQC cTy ++ "' to '" ++ TH.pprint hsTy ++ "'"
+    }
 generateHaskellToCMarshaller hsTy cTy
+  | Just hsMarshalTy <- Map.lookup cTy cIntegralMap    -- checking whether it is an integral type
+  = return ( hsMarshalTy
+           , cTy
+           , \val cont -> [| $cont (fromIntegral $val) |]
+           , \argName -> [cexp| $id:(show argName) |]
+           )
+  | Just hsMarshalTy <- Map.lookup cTy cFloatingMap    -- checking whether it is a floating type
+  = return ( hsMarshalTy
+           , cTy
+           , \val cont -> [| $cont (realToFrac $val) |]
+           , \argName -> [cexp| $id:(show argName) |]
+           )
   | cTy == [cty| typename NSString * |] 
   = return ( [t| C.CString |]
            , [cty| char * |]
@@ -150,7 +256,7 @@
   | otherwise
   = reportErrorAndFail ObjC $ "cannot marshal '" ++ TH.pprint hsTy ++ "' to '" ++ prettyQC cTy ++ "'"
 
--- Generate the type-specific marshalling code for Haskell to C land marshalling for a C-Haskell type pair.
+-- |Generate the type-specific marshalling code for Haskell to C land marshalling for a C-Haskell type pair.
 --
 -- The result has the following components:
 --
@@ -161,6 +267,18 @@
 --
 generateCToHaskellMarshaller :: TH.Type -> QC.Type -> Q (TH.TypeQ, QC.Type, HaskellMarshaller, CMarshaller)
 generateCToHaskellMarshaller hsTy cTy
+  | Just hsMarshalTy <- Map.lookup cTy cIntegralMap    -- checking whether it is an integral type
+  = return ( hsMarshalTy
+           , cTy
+           , \val cont -> [| $cont (fromIntegral $val) |]
+           , \argName -> [cexp| $id:(show argName) |]
+           )
+  | Just hsMarshalTy <- Map.lookup cTy cFloatingMap    -- checking whether it is a floating type
+  = return ( hsMarshalTy
+           , cTy
+           , \val cont -> [| $cont (realToFrac $val) |]
+           , \argName -> [cexp| $id:(show argName) |]
+           )
   | cTy == [cty| typename NSString * |]
   = return ( [t| C.CString |]
            , [cty| char * |]
@@ -192,3 +310,21 @@
   | otherwise
   = reportErrorAndFail ObjC $ "cannot marshall '" ++ prettyQC cTy ++ "' to '" ++ TH.pprint hsTy ++ "'"    
 
+cIntegralMap = Map.fromList
+               [ ([cty| char |],               [t| C.CChar |])
+               , ([cty| signed char |],        [t| C.CChar |])
+               , ([cty| unsigned char |],      [t| C.CUChar |])
+               , ([cty| short |],              [t| C.CShort |])
+               , ([cty| unsigned short |],     [t| C.CUShort |])
+               , ([cty| int |],                [t| C.CInt |])
+               , ([cty| unsigned int |],       [t| C.CUInt |])
+               , ([cty| long |],               [t| C.CLong |])
+               , ([cty| unsigned long |],      [t| C.CULong |])
+               , ([cty| long long |],          [t| C.CLLong |])
+               , ([cty| unsigned long long |], [t| C.CULLong |])
+               ]
+
+cFloatingMap = Map.fromList
+               [ ([cty| float |] , [t| C.CFloat |])
+               , ([cty| double |], [t| C.CDouble |])
+               ]
diff --git a/language-c-inline.cabal b/language-c-inline.cabal
--- a/language-c-inline.cabal
+++ b/language-c-inline.cabal
@@ -1,5 +1,5 @@
 Name:                   language-c-inline
-Version:                0.3.0.1
+Version:                0.5.0.0
 Cabal-version:          >= 1.9.2
 Tested-with:            GHC == 7.6.3
 Build-type:             Simple
@@ -16,6 +16,10 @@
                         .
                         Known bugs: <https://github.com/mchakravarty/language-c-inline/issues>
                         .
+                        * New in 0.5.0.0: Marshalling of numeric types
+                        .
+                        * New in 0.4.0.0: Maybe types are marshalled as pointers that may be nil & bug fixes.
+                        .
                         * New in 0.3.0.0: Boxed Haskell types without a dedicated type mapping are marshalled using stable
                         pointers.
                         .
@@ -35,7 +39,6 @@
 Stability:              Experimental
 
 Extra-source-files:     README.md
-                        tests/objc/concept/Makefile
                         tests/objc/app/App.hs
                         tests/objc/app/AppDelegate.hs
                         tests/objc/app/Interpreter.hs
@@ -47,8 +50,12 @@
                         tests/objc/app/HSApp.app/Contents/Resources/en.lproj/Credits.rtf
                         tests/objc/app/HSApp.app/Contents/Resources/en.lproj/InfoPlist.strings
                         tests/objc/app/HSApp.app/Contents/Resources/en.lproj/MainMenu.nib
+                        tests/objc/concept/Makefile
                         tests/objc/minimal/Makefile
                         tests/objc/minimal/Main.hs
+                        tests/objc/record/Makefile
+                        tests/objc/record/Main.hs
+                        tests/objc/record/Particle.hs
 
 Source-repository head
   Type:                 git
@@ -57,6 +64,7 @@
 Library
   Build-depends:        array,
                         base              >= 4.0 && < 5,
+                        containers        >= 0.4,
                         filepath          >= 1.2,
                         language-c-quote  >= 0.7,
                         mainland-pretty   >= 0.2.5,
diff --git a/tests/objc/app/AppDelegate.hs b/tests/objc/app/AppDelegate.hs
--- a/tests/objc/app/AppDelegate.hs
+++ b/tests/objc/app/AppDelegate.hs
@@ -30,7 +30,7 @@
                          { result <- typeOf session expr
                          ; return $ formatResult input result
                          }
-      (command, _)    -> return $ "Haskell> " ++ input ++ "\nUnknown command" ++ command ++ "\n"
+      (command, _)    -> return $ "Haskell> " ++ input ++ "\nUnknown command '" ++ command ++ "'\n"
 evalExpr session expr
   = do 
     { result <- eval session expr
diff --git a/tests/objc/app/Interpreter.hs b/tests/objc/app/Interpreter.hs
--- a/tests/objc/app/Interpreter.hs
+++ b/tests/objc/app/Interpreter.hs
@@ -21,9 +21,7 @@
 import Control.Concurrent
 import Control.Exception            (SomeException, evaluate)
 import Control.Monad
-import "MonadCatchIO-mtl" 
-       Control.Monad.CatchIO
-import Control.Monad.Error
+import Control.Monad.Catch
 
 import System.IO
 
@@ -80,9 +78,9 @@
     ; putMVar inlet $ Just $       -- the interpreter command we send over to the interpreter thread
         do
           {                  -- demand the result to force any contained exceptions
-          ; result <- (do { !result <- Interp.eval e
-                          ; return result }
-                      `catchError` (return . pprError))
+          ; result <- do { !result <- Interp.eval e
+                         ; return result }
+                      `catch` (return . pprError)
                       `catch` (return . (show :: SomeException -> String))
           ; Interp.lift $ putMVar resultMV (Result result)
           }
@@ -100,9 +98,9 @@
     ; putMVar inlet $ Just $       -- the interpreter command we send over to the interpreter thread
         do
           {                  -- demand the result to force any contained exceptions
-          ; result <- (do { !result <- Interp.typeOf e
-                          ; return result }
-                      `catchError` (return . pprError))
+          ; result <- do { !result <- Interp.typeOf e
+                         ; return result }
+                      `catch` (return . pprError)
                       `catch` (return . (show :: SomeException -> String))
           ; Interp.lift $ putMVar resultMV (Result result)
           }
@@ -120,11 +118,11 @@
     ; putMVar inlet $ Just $       -- the interpreter command we send over to the interpreter thread
         do
           {                  -- demand the result to force any contained exceptions
-          ; result <- (do { Interp.loadModules [mname]
-                          ; mods <- Interp.getLoadedModules
-                          ; Interp.setTopLevelModules mods
-                          ; return ("Successfully loaded '" ++ mname ++ "'") }
-                      `catchError` (return . pprError))
+          ; result <- do { Interp.loadModules [mname]
+                         ; mods <- Interp.getLoadedModules
+                         ; Interp.setTopLevelModules mods
+                         ; return ("Successfully loaded '" ++ mname ++ "'") }
+                      `catch` (return . pprError)
                       `catch` (return . (show :: SomeException -> String))
           ; Interp.lift $ putMVar resultMV (Result result)
           }
@@ -133,6 +131,6 @@
 
 pprError :: Interp.InterpreterError -> String
 pprError (Interp.UnknownError msg) = msg
-pprError (Interp.WontCompile errs) = "Compile time error: \n" ++ concatMap Interp.errMsg errs
+pprError (Interp.WontCompile errs) = "Compile time error: \n" ++ unlines (map Interp.errMsg errs)
 pprError (Interp.NotAllowed msg)   = "Permission denied: " ++ msg
 pprError (Interp.GhcException msg) = "Internal error: " ++ msg
diff --git a/tests/objc/concept/MainInlineObjC.hs b/tests/objc/concept/MainInlineObjC.hs
--- a/tests/objc/concept/MainInlineObjC.hs
+++ b/tests/objc/concept/MainInlineObjC.hs
@@ -4,5 +4,5 @@
 main
   = do
     { objc_initialise
-    ; dumpURL "https://raw.github.com/mchakravarty/language-c-inline/master/tests/objc/TestInlineObjC.hs"
+    ; dumpURL "https://raw.githubusercontent.com/mchakravarty/language-c-inline/master/tests/objc/concept/TestInlineObjC.hs"
     }
diff --git a/tests/objc/record/Main.hs b/tests/objc/record/Main.hs
new file mode 100644
--- /dev/null
+++ b/tests/objc/record/Main.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
+
+import Language.C.Quote.ObjC
+import Language.C.Inline.ObjC
+
+objc_import ["<Foundation/Foundation.h>", "Particle_objc.h"]
+
+go :: IO ()
+go = $(objc [] ''() [cexp| ({ 
+    typename Particle *particle = [Particle particleWithMass:1.0]; 
+    NSLog(@"The mass is %f", particle.mass); 
+  }) |])
+
+objc_emit
+
+
+main = objc_initialise >> go
diff --git a/tests/objc/record/Makefile b/tests/objc/record/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/objc/record/Makefile
@@ -0,0 +1,25 @@
+HC      = ghc
+CFLAGS  = -fobjc-arc -I$(shell $(HC) --print-libdir)/include
+HCFLAGS =
+LDFLAGS = -package template-haskell -package language-c-quote -package language-c-inline -framework Foundation
+
+OBJS = Main.o Main_objc.o Particle.o Particle_objc.o 
+
+default: Particle
+
+%.o: %.hs
+	$(HC) -c $< $(HCFLAGS)
+
+Particle.o:
+Main.o: Particle.o
+
+Main_objc.m: Main.o
+Particle_objc.m: Particle.o
+
+Particle: $(OBJS)
+	$(HC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+	rm -f *.o *.hi Main_objc.[hm] Particle_objc.[hm] *_stub.h Particle
diff --git a/tests/objc/record/Particle.hs b/tests/objc/record/Particle.hs
new file mode 100644
--- /dev/null
+++ b/tests/objc/record/Particle.hs
@@ -0,0 +1,96 @@
+{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
+
+-- Marshalling a record structure
+
+module Particle (objc_initialise) where
+
+  -- language-c-inline
+import Language.C.Quote.ObjC
+import Language.C.Inline.ObjC
+
+objc_import ["<Foundation/Foundation.h>", "HsFFI.h"]
+
+
+-- Haskell code used from Objective-C.
+
+type Point = (Float, Float)
+
+origin = (0, 0)
+
+newtype Vector = Vector (Float, Float)
+
+zero = Vector (0, 0)
+
+data Particle = Particle 
+                { mass :: Float
+                , loc  :: Point
+                , vel  :: Vector
+                , acc  :: Vector
+                }
+
+newParticle :: Float -> Particle
+newParticle mass = Particle mass origin zero zero
+
+particleMass :: Particle -> Float
+particleMass = mass
+
+
+objc_interface [cunit|
+
+@interface Particle : NSObject
+
+@property (readonly) float mass;
+
++ (typename instancetype)particleWithMass:(float)mass;
+
+- (typename instancetype)init;
+
+- (typename instancetype)initWithMass:(float)mass;
+
+
+@end
+|]
+
+
+objc_implementation ['newParticle, 'particleMass] [cunit|
+
+@interface Particle ()
+
+@property (readonly, assign, nonatomic) typename HsStablePtr particle;
+
+@end
+
+@implementation Particle
+
+// Initialisation
+
++ (typename instancetype)particleWithMass:(float)mass
+{
+  return [[Particle alloc] initWithMass:mass];
+}
+
+- (typename instancetype)init
+{
+  return [self initWithMass:0.0];
+}
+
+- (typename instancetype)initWithMass:(float)mass
+{
+  self = [super init];
+  if (self)
+    _particle = newParticle(mass);
+  return self;
+}
+
+// Getters and setters
+
+- (float)mass
+{
+  return particleMass(self.particle);
+}
+
+@end
+|]
+
+
+objc_emit
