diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
 # foreign
 
-A collection of data types, classes, and functions for easing your ffi
-experience.
+Extra collection of data types, classes, and functions for interfacing with c
+and c++.
diff --git a/foreign.cabal b/foreign.cabal
--- a/foreign.cabal
+++ b/foreign.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               foreign
-version:            0.1.1.0
+version:            0.1.2.0
 synopsis:           A collection of helpers for ffi.
 description:
   Please see the README on Github at <https://github.com/4eUeP/foreign#readme>
@@ -52,6 +52,7 @@
     HsForeign.AsyncFFI
     HsForeign.Primitive
     HsForeign.String
+    HsForeign.Utils
 
   build-depends:
     , base                >=4.14 && <5
diff --git a/src/HsForeign.hs b/src/HsForeign.hs
--- a/src/HsForeign.hs
+++ b/src/HsForeign.hs
@@ -2,8 +2,10 @@
   ( module HsForeign.Primitive
   , module HsForeign.AsyncFFI
   , module HsForeign.String
+  , module HsForeign.Utils
   ) where
 
 import           HsForeign.AsyncFFI
 import           HsForeign.Primitive
 import           HsForeign.String
+import           HsForeign.Utils
diff --git a/src/HsForeign/Primitive.hs b/src/HsForeign/Primitive.hs
--- a/src/HsForeign/Primitive.hs
+++ b/src/HsForeign/Primitive.hs
@@ -24,7 +24,7 @@
   , byteArrayContents#
   , mutableByteArrayContents#
 
-    -- * Re-export
+    -- * Re-exports
   , module Data.Primitive
   , module Control.Monad.Primitive
   ) where
diff --git a/src/HsForeign/String.hs b/src/HsForeign/String.hs
--- a/src/HsForeign/String.hs
+++ b/src/HsForeign/String.hs
@@ -1,12 +1,24 @@
+{-# LANGUAGE BangPatterns    #-}
+{-# LANGUAGE CPP             #-}
+{-# LANGUAGE MagicHash       #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE TupleSections   #-}
+
 module HsForeign.String
   ( -- * CString
     mallocFromByteString
   , mallocFromMaybeByteString
+  , newStablePtrByteString
   , withByteString
+  , withMaybeByteString
+  , withByteStringList
   , withByteStrings
+  , withShortByteString
 
     -- * CXX: std::string
   , StdString
+  , newStdString
+  , maybeNewStdString
   , hs_new_std_string
   , hs_new_std_string_def
   , hs_std_string_size
@@ -15,16 +27,21 @@
   , unsafePeekStdString
   ) where
 
-import           Control.Exception        (AssertionFailed (..), throw)
-import           Control.Monad            (unless)
-import           Data.ByteString          (ByteString)
-import qualified Data.ByteString.Internal as BS
-import qualified Data.ByteString.Unsafe   as BS
+import           Control.Exception              (AssertionFailed (..), throw)
+import           Control.Monad                  (unless)
+import           Data.ByteString                (ByteString)
+import qualified Data.ByteString.Internal       as BS
+import           Data.ByteString.Short          (ShortByteString)
+import qualified Data.ByteString.Short.Internal as BSS
+import qualified Data.ByteString.Unsafe         as BS
 import           Data.Word
 import           Foreign.C.String
 import           Foreign.ForeignPtr
+import           Foreign.ForeignPtr.Unsafe
 import           Foreign.Marshal
 import           Foreign.Ptr
+import           Foreign.StablePtr
+import           GHC.Exts                       (touch#)
 
 import           HsForeign.Primitive
 
@@ -48,15 +65,42 @@
 mallocFromMaybeByteString Nothing   = return (nullPtr, 0)
 {-# INLINE mallocFromMaybeByteString #-}
 
+newStablePtrByteString :: ByteString -> IO (CString, Int, StablePtr ByteString)
+newStablePtrByteString bs = do
+  !sp <- newStablePtr bs
+  let (fp, len) = toForeignPtr0 bs
+      !p = unsafeForeignPtrToPtr fp
+  pure (castPtr p, len, sp)
+
 withByteString :: ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a
-withByteString (BS.PS fp off len) f =
-  -- TODO: since bytestring 0.11.0.0, it exports the 'BS' constructor.
-  -- we can change to benefit from the simplified BS constructor if we only
-  -- support bytestring >= 0.11
-  let fp' = fp `plusForeignPtr` off
-   in withForeignPtr fp' $ \p -> f p len
+withByteString bs f =
+  let (fp, len) = toForeignPtr0 bs
+   in withForeignPtr fp $ \p -> f p len
+{-# INLINABLE withByteString #-}
 
+withMaybeByteString :: Maybe ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a
+withMaybeByteString Nothing f = f nullPtr 0
+withMaybeByteString (Just bs) f =
+  let (fp, len) = toForeignPtr0 bs
+   in withForeignPtr fp $ \p -> f p len
+{-# INLINABLE withMaybeByteString #-}
+
 -- | Pass list of ByteStrings to FFI.
+withByteStringList
+  :: [ByteString]
+  -> (Ptr (Ptr Word8) -> Ptr Int -> Int -> IO a)
+  -- ^ cstring*, len*, list_len
+  -> IO a
+withByteStringList bss f = do
+  let (ps, lens) = unzip (map toForeignPtr0 bss)
+  withPrimArray (primArrayFromList lens) $ \lens' num ->
+    withForeignPtrList ps $ \ps' num_ps -> do
+      unless (num == num_ps) $ throw $
+        AssertionFailed "This should never happen..."
+      f ps' lens' num
+
+{-# DEPRECATED withByteStrings "use withByteStringList instead" #-}
+-- | Pass list of ByteStrings to FFI.
 withByteStrings
   :: [ByteString]
   -> (Ptr (Ptr Word8) -> Ptr Int -> Ptr Int -> Int -> IO a)
@@ -72,6 +116,12 @@
         AssertionFailed "This should never happen..."
       f ps' offs' lens' num
 
+withShortByteString :: ShortByteString -> (ByteArray# -> Int -> IO a) -> IO a
+withShortByteString sbs@(BSS.SBS ba#) f = do
+  !r <- f ba# (BSS.length sbs)
+  primitive_ $ touch# ba#
+  pure r
+
 -------------------------------------------------------------------------------
 -- std::string
 
@@ -83,9 +133,33 @@
 foreign import ccall unsafe hs_std_string_cstr :: Ptr StdString -> IO (Ptr Word8)
 foreign import ccall unsafe hs_delete_std_string :: Ptr StdString -> IO ()
 
+-- | New a c++ std::string from proviced bytestring.
+--
+-- The memory should be deallocated using delete when no longer required.
+newStdString :: ByteString -> IO (Ptr StdString)
+newStdString bs = withByteString bs $ hs_new_std_string
+
+maybeNewStdString :: Maybe ByteString -> IO (Ptr StdString)
+maybeNewStdString Nothing   = pure nullPtr
+maybeNewStdString (Just bs) = newStdString bs
+
 unsafePeekStdString :: Ptr StdString -> IO ByteString
 unsafePeekStdString stdstring = do
   siz <- hs_std_string_size stdstring
   ptr <- hs_std_string_cstr stdstring
   BS.unsafePackCStringFinalizer ptr siz (hs_delete_std_string stdstring)
 {-# INLINE unsafePeekStdString #-}
+
+-------------------------------------------------------------------------------
+
+-- TODO: since bytestring 0.11.0.0, it exports the 'BS' constructor and
+-- 'toForeignPtr0'.
+--
+-- we can change to benefit from the simplified BS constructor if we only
+-- support bytestring >= 0.11
+toForeignPtr0 :: ByteString -> (ForeignPtr Word8, Int)
+#if !MIN_VERSION_bytestring(0, 11, 0)
+toForeignPtr0 (BS.PS fp off len) = (fp `plusForeignPtr` off, len)
+#else
+toForeignPtr0 = BS.toForeignPtr0
+#endif
diff --git a/src/HsForeign/Utils.hs b/src/HsForeign/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/HsForeign/Utils.hs
@@ -0,0 +1,14 @@
+module HsForeign.Utils
+  ( withMaybePtr
+  ) where
+
+import           Foreign.Ptr
+
+withMaybePtr
+  :: Maybe a
+  -> (a -> (Ptr a -> IO b) -> IO b)
+  -> (Ptr a -> IO b)
+  -> IO b
+withMaybePtr Nothing _withx f = f nullPtr
+withMaybePtr (Just x) withx f = withx x f
+{-# INLINABLE withMaybePtr #-}
