|
From: <cod...@go...> - 2008-10-19 20:58:35
|
Author: wol...@gm...
Date: Sun Oct 19 13:57:37 2008
New Revision: 340
Modified:
trunk/hoc/HOC/HOC/FFICallInterface.hs
trunk/hoc/HOC/HOC/Invocation.hs
Log:
libffi returns small integral return values promoted to long.
Deal with it.
Modified: trunk/hoc/HOC/HOC/FFICallInterface.hs
==============================================================================
--- trunk/hoc/HOC/HOC/FFICallInterface.hs (original)
+++ trunk/hoc/HOC/HOC/FFICallInterface.hs Sun Oct 19 13:57:37 2008
@@ -1,4 +1,11 @@
-module HOC.FFICallInterface where
+module HOC.FFICallInterface(
+ FFICif,
+ FFIType,
+ FFITypeable(..),
+ ffiPrepCif,
+ makeStructType,
+ cifIsStret
+ ) where
import Foreign.C.Types
import Foreign
@@ -15,6 +22,17 @@
isStructType :: a -> Bool
isStructType _ = False
+
+ -- Integral return values of size < sizeof(long) require special
treatment
+ -- in libffi; they are returned as long. For these types, the following
+ -- gives us a chance to replace alloca & peek with a version that
undoes
+ -- the promotion.
+
+ peekRetval :: Storable a => Ptr a -> IO a
+ allocaRetval :: Storable a => (Ptr a -> IO b) -> IO b
+
+ peekRetval = peek
+ allocaRetval = alloca
foreign import ccall "ffi.h &ffi_type_void" ffi_type_void :: FFIType
foreign import ccall "ffi.h &ffi_type_uint8" ffi_type_uint8:: FFIType
@@ -54,6 +72,15 @@
foreign import ccall unsafe cifIsStret :: FFICif -> IO CInt
+promotedPeek p
+ = peek (castPtr p :: Ptr CLong) >>= return . fromIntegral
+ where
+ size = sizeOf (pointee p)
+ pointee :: Ptr p -> p
+ pointee = undefined
+
+promotedAlloca f = alloca (\intPtr -> f $ castPtr (intPtr :: Ptr CLong))
+
-- typeable instances
instance FFITypeable () where
@@ -64,19 +91,43 @@
instance FFITypeable Int8 where
makeFFIType _ = return ffi_type_sint8
+
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
+
instance FFITypeable Int16 where
makeFFIType _ = return ffi_type_sint16
+
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
+
instance FFITypeable Int32 where
makeFFIType _ = return ffi_type_sint32
+
+ peekRetval = promotedPeek -- only takes effect on 64-bit
+ allocaRetval = promotedAlloca
+
instance FFITypeable Int64 where
makeFFIType _ = return ffi_type_sint64
instance FFITypeable Word8 where
makeFFIType _ = return ffi_type_uint8
+
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
+
instance FFITypeable Word16 where
makeFFIType _ = return ffi_type_uint16
+
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
+
instance FFITypeable Word32 where
makeFFIType _ = return ffi_type_uint32
+
+ peekRetval = promotedPeek -- only takes effect on 64-bit
+ allocaRetval = promotedAlloca
+
instance FFITypeable Word64 where
makeFFIType _ = return ffi_type_uint64
@@ -101,20 +152,34 @@
instance FFITypeable CChar where
makeFFIType _ = return ffi_type_sint8
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
instance FFITypeable CUChar where
makeFFIType _ = return ffi_type_uint8
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
instance FFITypeable CSChar where
makeFFIType _ = return ffi_type_sint8
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
instance FFITypeable CShort where
makeFFIType _ = return ffi_type_sint16
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
instance FFITypeable CUShort where
makeFFIType _ = return ffi_type_uint16
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
instance FFITypeable CInt where
makeFFIType _ = return ffi_type_sint32
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
instance FFITypeable CUInt where
makeFFIType _ = return ffi_type_uint32
+ peekRetval = promotedPeek
+ allocaRetval = promotedAlloca
instance FFITypeable CLong where
makeFFIType _ = return ffi_type_sint32
Modified: trunk/hoc/HOC/HOC/Invocation.hs
==============================================================================
--- trunk/hoc/HOC/HOC/Invocation.hs (original)
+++ trunk/hoc/HOC/HOC/Invocation.hs Sun Oct 19 13:57:37 2008
@@ -38,9 +38,9 @@
-> IO b
callWithRetval cif fun args = do
- alloca $ \retptr ->
+ allocaRetval $ \retptr ->
callWithException cif fun retptr args
- >> peek retptr >>= importArgument
+ >> peekRetval retptr >>= importArgument
setMarshalledRetval :: ObjCArgument a b => Bool -> Ptr () -> a -> IO ()
|