codeHookAdd :: Storable a
            => Engine           -- ^ 'Unicorn' engine handle
            -> CodeHook a       -- ^ Code hook callback
            -> a                -- ^ User-defined data. This will be passed to
                                -- the callback function
            -> Word64           -- ^ Start address
            -> Word64           -- ^ End address
            -> Emulator Hook    -- ^ The hook handle on success, or an 'Error'
                                -- on failure
codeHookAdd uc callback userData begin end = do
    result <- lift . alloca $ \userDataPtr -> do
        poke userDataPtr userData
        funPtr <- marshalCodeHook callback
        getResult $ ucHookAdd uc HookCode funPtr userDataPtr begin end
    hoistEither result

-- | Register a callback for an interrupt hook event.
codeHookAdd :: Storable a
            => Engine           -- ^ 'Unicorn' engine handle
            -> CodeHook a       -- ^ Code hook callback
            -> a                -- ^ User-defined data. This will be passed to
                                -- the callback function
            -> Word64           -- ^ Start address
            -> Word64           -- ^ End address
            -> Emulator Hook
codeHookAdd uc callback userData begin end = do
    result <- lift . alloca $ \userDataPtr -> do
        poke userDataPtr userData
        funPtr <- marshalCodeHook callback
        getResult $ ucHookAdd uc HookCode funPtr userDataPtr begin end
    hoistEither result

-- | Register a callback for an interrupt hook event.
codeHookAdd uc callback userData begin end = do
    result <- lift . alloca $ \userDataPtr -> do
        poke userDataPtr userData
        funPtr <- marshalCodeHook callback
        getResult $ ucHookAdd uc HookCode funPtr userDataPtr begin end
    hoistEither result

-- | Register a callback for an interrupt hook event.