inline-c 0.6.0.6 → 0.6.1.0
raw patch · 3 files changed
+61/−3 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Language.C.Inline.Internal: splitTypedC :: String -> (String, String)
Files
- inline-c.cabal +3/−1
- src/Language/C/Inline/Context.hs +47/−2
- src/Language/C/Inline/Internal.hs +11/−0
inline-c.cabal view
@@ -1,5 +1,5 @@ name: inline-c-version: 0.6.0.6+version: 0.6.1.0 synopsis: Write Haskell source files including C code inline. No FFI required. description: See <https://github.com/fpco/inline-c/blob/master/README.md>. license: MIT@@ -72,6 +72,7 @@ , vector default-language: Haskell2010 ghc-options: -Wall+ cc-options: -Wall -Werror executable gsl-ode hs-source-dirs: examples@@ -79,6 +80,7 @@ default-language: Haskell2010 extra-libraries: gsl gslcblas m ghc-options: -Wall+ cc-options: -Wall -Werror if flag(gsl-example) buildable: True
src/Language/C/Inline/Context.hs view
@@ -330,7 +330,8 @@ } -- | This 'Context' includes a 'AntiQuoter' that removes the need for--- explicitely creating 'FunPtr's, named @"fun"@.+-- explicitely creating 'FunPtr's, named @"fun"@ along with one which+-- allocates new memory which must be manually freed named @"fun-alloc"@. -- -- For example, we can capture function @f@ of type @CInt -> CInt -> IO -- CInt@ in C code using @$fun:(int (*f)(int, int))@.@@ -349,9 +350,15 @@ -- allocate it and free it manually using 'freeHaskellFunPtr'. -- We provide utilities to easily -- allocate them (see 'Language.C.Inline.mkFunPtr').+--+-- IMPORTANT: When using the @fun-alloc@ anti quoter, one must free the allocated+-- function pointer. The GHC runtime provides a function to do this,+-- 'hs_free_fun_ptr' available in the 'HsFFI.h' header.+ funCtx :: Context funCtx = mempty- { ctxAntiQuoters = Map.fromList [("fun", SomeAntiQuoter funPtrAntiQuoter)]+ { ctxAntiQuoters = Map.fromList [("fun", SomeAntiQuoter funPtrAntiQuoter)+ ,("fun-alloc", SomeAntiQuoter funAllocPtrAntiQuoter)] } funPtrAntiQuoter :: AntiQuoter HaskellIdentifier@@ -372,6 +379,22 @@ _ -> fail "The `fun' marshaller captures function pointers only" } +funAllocPtrAntiQuoter :: AntiQuoter HaskellIdentifier+funAllocPtrAntiQuoter = AntiQuoter+ { aqParser = cDeclAqParser+ , aqMarshaller = \purity cTypes cTy cId -> do+ hsTy <- convertType_ "funCtx" purity cTypes cTy+ hsExp <- getHsVariable "funCtx" cId+ case hsTy of+ TH.AppT (TH.ConT n) hsTy' | n == ''FunPtr -> do+ hsExp' <- [| \cont -> do+ funPtr <- $(mkFunPtr (return hsTy')) $(return hsExp)+ cont funPtr+ |]+ return (hsTy, hsExp')+ _ -> fail "The `fun-alloc' marshaller captures function pointers only"+ }+ -- | This 'Context' includes two 'AntiQuoter's that allow to easily use -- Haskell vectors in C. --@@ -447,11 +470,15 @@ -- 'BS.ByteString'. @vec-ptr@ becomes @bs-ptr@, and @vec-len@ becomes -- @bs-len@. You don't need to specify the type of the pointer in -- @bs-ptr@, it will always be @char*@.+--+-- Moreover, @bs-cstr@ works as @bs-ptr@ but it provides a null-terminated+-- copy of the given 'BS.ByteString'. bsCtx :: Context bsCtx = mempty { ctxAntiQuoters = Map.fromList [ ("bs-ptr", SomeAntiQuoter bsPtrAntiQuoter) , ("bs-len", SomeAntiQuoter bsLenAntiQuoter)+ , ("bs-cstr", SomeAntiQuoter bsCStrAntiQuoter) ] } @@ -489,6 +516,24 @@ _ -> do fail "impossible: got type different from `long' (bsCtx)" }++bsCStrAntiQuoter :: AntiQuoter HaskellIdentifier+bsCStrAntiQuoter = AntiQuoter+ { aqParser = do+ hId <- C.parseIdentifier+ let cId = mangleHaskellIdentifier hId+ return (cId, C.Ptr [] (C.TypeSpecifier mempty (C.Char Nothing)), hId)+ , aqMarshaller = \_purity _cTypes cTy cId -> do+ case cTy of+ C.Ptr _ (C.TypeSpecifier _ (C.Char Nothing)) -> do+ hsTy <- [t| Ptr CChar |]+ hsExp <- getHsVariable "bsCtx" cId+ hsExp' <- [| \cont -> BS.useAsCString $(return hsExp) $ \ptr -> cont ptr |]+ return (hsTy, hsExp')+ _ ->+ fail "impossible: got type different from `char *' (bsCtx)"+ }+ -- Utils ------------------------------------------------------------------------
src/Language/C/Inline/Internal.hs view
@@ -45,6 +45,7 @@ , ParseTypedC(..) , parseTypedC , runParserInQ+ , splitTypedC -- * Utility functions for writing quasiquoters , genericQuote@@ -71,6 +72,8 @@ import qualified Text.Parser.Token as Parser import Text.PrettyPrint.ANSI.Leijen ((<+>)) import qualified Text.PrettyPrint.ANSI.Leijen as PP+import qualified Data.List as L+import qualified Data.Char as C -- We cannot use getQ/putQ before 7.10.3 because of <https://ghc.haskell.org/trac/ghc/ticket/10596> #define USE_GETQ (__GLASGOW_HASKELL__ > 710 || (__GLASGOW_HASKELL__ == 710 && __GLASGOW_HASKELL_PATCHLEVEL1__ >= 3))@@ -579,6 +582,14 @@ [t| IO $(return retType) |] go (paramType : params) = do [t| $(return paramType) -> $(go params) |]++splitTypedC :: String -> (String, String)+ -- ^ Returns the type and the body separately+splitTypedC s = (trim ty, case body of+ [] -> []+ r -> r)+ where (ty, body) = span (/= '{') s+ trim x = L.dropWhileEnd C.isSpace (dropWhile C.isSpace x) ------------------------------------------------------------------------ -- Utils