8
--- DESCRIPTION ---------------------------------------------------------------
12
--- DOCU ----------------------------------------------------------------------
15
--- TODO ----------------------------------------------------------------------
18
module C2HSDeprecated (
19
-- the `Addr' module is gone in the New FFI
20
Addr, nullAddr, plusAddr, alignAddr, minusAddr,
21
-- the names of theses types did change
22
CSInt, CLInt, CLLInt, CUSInt, CULInt, CULLInt,
23
-- old C2HS-style Storable support PLUS the methods of the new Storable
24
Storable(..), assignOff, derefOff, assign_, deref_,
25
assignOff_, derefOff_,
26
-- these have different names now
28
-- old conversion interface
29
cToChar, cFromChar, cToInt, cFromInt, cToFloat, cFromFloat, cToDouble,
31
-- old serialisation interface
32
ToAddr(stdAddr), FromAddr(addrStdKeep), addrStd,
33
-- exception handling is now part of the standard FFI
34
ifRaise, ifNegRaise, ifNegRaise_, ifNullRaise,
35
-- old (de)serilisation of lists
36
listToAddrWithLen, addrWithLenToList, listToAddrWithMarker,
38
-- marshalling templates
39
Marsh(..), marsh1, marsh1_, marsh2, marsh2_, marsh3, marsh3_, use, forget,
40
void, ref, toAddr, toAddrKeep, toFromAddr,
42
-- we ex-export all of the new interface that doesn't clash with any of the
43
-- old definitions (namespace-wise)
48
import Monad (liftM, when)
50
(Storable(..), malloc, void)
52
C2HS (Storable(..), malloc)
58
nullAddr = nullPtr :: Addr
71
type CULLInt = CULLong
76
mallocBySize :: Int -> IO Addr
77
mallocBySize = C2HS.mallocBytes
80
malloc :: Storable a => a -> IO Addr
81
malloc = mallocBySize . sizeof
84
class Storable a where
86
assign :: Addr -> a -> IO Addr
87
deref :: Addr -> IO (a, Addr)
91
peekElemOff :: Ptr a -> Int -> IO a
92
pokeElemOff :: Ptr a -> Int -> a -> IO ()
93
peekByteOff :: Ptr b -> Int -> IO a
94
pokeByteOff :: Ptr b -> Int -> a -> IO ()
96
poke :: Ptr a -> a -> IO ()
98
sizeOf :: Storable a => a -> Int
101
instance Storable Char where
104
C2HS.poke (castPtr addr) v
105
return (addr `plusPtr` sizeof v)
107
v <- C2HS.peek (castPtr addr)
108
return (v, addr `plusPtr` sizeof v)
110
alignment = C2HS.alignment
111
peekElemOff = C2HS.peekElemOff
112
pokeElemOff = C2HS.pokeElemOff
113
peekByteOff = C2HS.peekByteOff
114
pokeByteOff = C2HS.pokeByteOff
117
instance Storable Int where
120
C2HS.poke (castPtr addr) v
121
return (addr `plusPtr` sizeof v)
123
v <- C2HS.peek (castPtr addr)
124
return (v, addr `plusPtr` sizeof v)
126
alignment = C2HS.alignment
127
peekElemOff = C2HS.peekElemOff
128
pokeElemOff = C2HS.pokeElemOff
129
peekByteOff = C2HS.peekByteOff
130
pokeByteOff = C2HS.pokeByteOff
133
instance Storable Int8 where
136
C2HS.poke (castPtr addr) v
137
return (addr `plusPtr` sizeof v)
139
v <- C2HS.peek (castPtr addr)
140
return (v, addr `plusPtr` sizeof v)
142
alignment = C2HS.alignment
143
peekElemOff = C2HS.peekElemOff
144
pokeElemOff = C2HS.pokeElemOff
145
peekByteOff = C2HS.peekByteOff
146
pokeByteOff = C2HS.pokeByteOff
149
instance Storable Int16 where
152
C2HS.poke (castPtr addr) v
153
return (addr `plusPtr` sizeof v)
155
v <- C2HS.peek (castPtr addr)
156
return (v, addr `plusPtr` sizeof v)
158
alignment = C2HS.alignment
159
peekElemOff = C2HS.peekElemOff
160
pokeElemOff = C2HS.pokeElemOff
161
peekByteOff = C2HS.peekByteOff
162
pokeByteOff = C2HS.pokeByteOff
165
instance Storable Int32 where
168
C2HS.poke (castPtr addr) v
169
return (addr `plusPtr` sizeof v)
171
v <- C2HS.peek (castPtr addr)
172
return (v, addr `plusPtr` sizeof v)
174
alignment = C2HS.alignment
175
peekElemOff = C2HS.peekElemOff
176
pokeElemOff = C2HS.pokeElemOff
177
peekByteOff = C2HS.peekByteOff
178
pokeByteOff = C2HS.pokeByteOff
181
instance Storable Int64 where
184
C2HS.poke (castPtr addr) v
185
return (addr `plusPtr` sizeof v)
187
v <- C2HS.peek (castPtr addr)
188
return (v, addr `plusPtr` sizeof v)
190
alignment = C2HS.alignment
191
peekElemOff = C2HS.peekElemOff
192
pokeElemOff = C2HS.pokeElemOff
193
peekByteOff = C2HS.peekByteOff
194
pokeByteOff = C2HS.pokeByteOff
197
instance Storable Word8 where
200
C2HS.poke (castPtr addr) v
201
return (addr `plusPtr` sizeof v)
203
v <- C2HS.peek (castPtr addr)
204
return (v, addr `plusPtr` sizeof v)
206
alignment = C2HS.alignment
207
peekElemOff = C2HS.peekElemOff
208
pokeElemOff = C2HS.pokeElemOff
209
peekByteOff = C2HS.peekByteOff
210
pokeByteOff = C2HS.pokeByteOff
213
instance Storable Word16 where
216
C2HS.poke (castPtr addr) v
217
return (addr `plusPtr` sizeof v)
219
v <- C2HS.peek (castPtr addr)
220
return (v, addr `plusPtr` sizeof v)
222
alignment = C2HS.alignment
223
peekElemOff = C2HS.peekElemOff
224
pokeElemOff = C2HS.pokeElemOff
225
peekByteOff = C2HS.peekByteOff
226
pokeByteOff = C2HS.pokeByteOff
229
instance Storable Word32 where
232
C2HS.poke (castPtr addr) v
233
return (addr `plusPtr` sizeof v)
235
v <- C2HS.peek (castPtr addr)
236
return (v, addr `plusPtr` sizeof v)
238
alignment = C2HS.alignment
239
peekElemOff = C2HS.peekElemOff
240
pokeElemOff = C2HS.pokeElemOff
241
peekByteOff = C2HS.peekByteOff
242
pokeByteOff = C2HS.pokeByteOff
245
instance Storable Word64 where
248
C2HS.poke (castPtr addr) v
249
return (addr `plusPtr` sizeof v)
251
v <- C2HS.peek (castPtr addr)
252
return (v, addr `plusPtr` sizeof v)
254
alignment = C2HS.alignment
255
peekElemOff = C2HS.peekElemOff
256
pokeElemOff = C2HS.pokeElemOff
257
peekByteOff = C2HS.peekByteOff
258
pokeByteOff = C2HS.pokeByteOff
261
instance Storable Float where
264
C2HS.poke (castPtr addr) v
265
return (addr `plusPtr` sizeof v)
267
v <- C2HS.peek (castPtr addr)
268
return (v, addr `plusPtr` sizeof v)
270
alignment = C2HS.alignment
271
peekElemOff = C2HS.peekElemOff
272
pokeElemOff = C2HS.pokeElemOff
273
peekByteOff = C2HS.peekByteOff
274
pokeByteOff = C2HS.pokeByteOff
277
instance Storable Double where
280
C2HS.poke (castPtr addr) v
281
return (addr `plusPtr` sizeof v)
283
v <- C2HS.peek (castPtr addr)
284
return (v, addr `plusPtr` sizeof v)
286
alignment = C2HS.alignment
287
peekElemOff = C2HS.peekElemOff
288
pokeElemOff = C2HS.pokeElemOff
289
peekByteOff = C2HS.peekByteOff
290
pokeByteOff = C2HS.pokeByteOff
293
instance Storable Addr where
296
C2HS.poke (castPtr addr) v
297
return (addr `plusPtr` sizeof v)
299
v <- C2HS.peek (castPtr addr)
300
return (v, addr `plusPtr` sizeof v)
302
alignment = C2HS.alignment
303
peekElemOff = C2HS.peekElemOff
304
pokeElemOff = C2HS.pokeElemOff
305
peekByteOff = C2HS.peekByteOff
306
pokeByteOff = C2HS.pokeByteOff
310
instance Storable CChar where
313
C2HS.poke (castPtr addr) v
314
return (addr `plusPtr` sizeof v)
316
v <- C2HS.peek (castPtr addr)
317
return (v, addr `plusPtr` sizeof v)
319
alignment = C2HS.alignment
320
peekElemOff = C2HS.peekElemOff
321
pokeElemOff = C2HS.pokeElemOff
322
peekByteOff = C2HS.peekByteOff
323
pokeByteOff = C2HS.pokeByteOff
326
instance Storable CSChar where
329
C2HS.poke (castPtr addr) v
330
return (addr `plusPtr` sizeof v)
332
v <- C2HS.peek (castPtr addr)
333
return (v, addr `plusPtr` sizeof v)
335
alignment = C2HS.alignment
336
peekElemOff = C2HS.peekElemOff
337
pokeElemOff = C2HS.pokeElemOff
338
peekByteOff = C2HS.peekByteOff
339
pokeByteOff = C2HS.pokeByteOff
342
instance Storable CUChar where
345
C2HS.poke (castPtr addr) v
346
return (addr `plusPtr` sizeof v)
348
v <- C2HS.peek (castPtr addr)
349
return (v, addr `plusPtr` sizeof v)
351
alignment = C2HS.alignment
352
peekElemOff = C2HS.peekElemOff
353
pokeElemOff = C2HS.pokeElemOff
354
peekByteOff = C2HS.peekByteOff
355
pokeByteOff = C2HS.pokeByteOff
358
instance Storable CShort where
361
C2HS.poke (castPtr addr) v
362
return (addr `plusPtr` sizeof v)
364
v <- C2HS.peek (castPtr addr)
365
return (v, addr `plusPtr` sizeof v)
367
alignment = C2HS.alignment
368
peekElemOff = C2HS.peekElemOff
369
pokeElemOff = C2HS.pokeElemOff
370
peekByteOff = C2HS.peekByteOff
371
pokeByteOff = C2HS.pokeByteOff
374
instance Storable CUShort where
377
C2HS.poke (castPtr addr) v
378
return (addr `plusPtr` sizeof v)
380
v <- C2HS.peek (castPtr addr)
381
return (v, addr `plusPtr` sizeof v)
383
alignment = C2HS.alignment
384
peekElemOff = C2HS.peekElemOff
385
pokeElemOff = C2HS.pokeElemOff
386
peekByteOff = C2HS.peekByteOff
387
pokeByteOff = C2HS.pokeByteOff
390
instance Storable CInt where
393
C2HS.poke (castPtr addr) v
394
return (addr `plusPtr` sizeof v)
396
v <- C2HS.peek (castPtr addr)
397
return (v, addr `plusPtr` sizeof v)
399
alignment = C2HS.alignment
400
peekElemOff = C2HS.peekElemOff
401
pokeElemOff = C2HS.pokeElemOff
402
peekByteOff = C2HS.peekByteOff
403
pokeByteOff = C2HS.pokeByteOff
406
instance Storable CUInt where
409
C2HS.poke (castPtr addr) v
410
return (addr `plusPtr` sizeof v)
412
v <- C2HS.peek (castPtr addr)
413
return (v, addr `plusPtr` sizeof v)
415
alignment = C2HS.alignment
416
peekElemOff = C2HS.peekElemOff
417
pokeElemOff = C2HS.pokeElemOff
418
peekByteOff = C2HS.peekByteOff
419
pokeByteOff = C2HS.pokeByteOff
422
instance Storable CLong where
425
C2HS.poke (castPtr addr) v
426
return (addr `plusPtr` sizeof v)
428
v <- C2HS.peek (castPtr addr)
429
return (v, addr `plusPtr` sizeof v)
431
alignment = C2HS.alignment
432
peekElemOff = C2HS.peekElemOff
433
pokeElemOff = C2HS.pokeElemOff
434
peekByteOff = C2HS.peekByteOff
435
pokeByteOff = C2HS.pokeByteOff
438
instance Storable CULong where
441
C2HS.poke (castPtr addr) v
442
return (addr `plusPtr` sizeof v)
444
v <- C2HS.peek (castPtr addr)
445
return (v, addr `plusPtr` sizeof v)
447
alignment = C2HS.alignment
448
peekElemOff = C2HS.peekElemOff
449
pokeElemOff = C2HS.pokeElemOff
450
peekByteOff = C2HS.peekByteOff
451
pokeByteOff = C2HS.pokeByteOff
454
instance Storable CLLong where
457
C2HS.poke (castPtr addr) v
458
return (addr `plusPtr` sizeof v)
460
v <- C2HS.peek (castPtr addr)
461
return (v, addr `plusPtr` sizeof v)
463
alignment = C2HS.alignment
464
peekElemOff = C2HS.peekElemOff
465
pokeElemOff = C2HS.pokeElemOff
466
peekByteOff = C2HS.peekByteOff
467
pokeByteOff = C2HS.pokeByteOff
470
instance Storable CULLong where
473
C2HS.poke (castPtr addr) v
474
return (addr `plusPtr` sizeof v)
476
v <- C2HS.peek (castPtr addr)
477
return (v, addr `plusPtr` sizeof v)
479
alignment = C2HS.alignment
480
peekElemOff = C2HS.peekElemOff
481
pokeElemOff = C2HS.pokeElemOff
482
peekByteOff = C2HS.peekByteOff
483
pokeByteOff = C2HS.pokeByteOff
487
instance Storable CFloat where
490
C2HS.poke (castPtr addr) v
491
return (addr `plusPtr` sizeof v)
493
v <- C2HS.peek (castPtr addr)
494
return (v, addr `plusPtr` sizeof v)
496
alignment = C2HS.alignment
497
peekElemOff = C2HS.peekElemOff
498
pokeElemOff = C2HS.pokeElemOff
499
peekByteOff = C2HS.peekByteOff
500
pokeByteOff = C2HS.pokeByteOff
503
instance Storable CDouble where
506
C2HS.poke (castPtr addr) v
507
return (addr `plusPtr` sizeof v)
509
v <- C2HS.peek (castPtr addr)
510
return (v, addr `plusPtr` sizeof v)
512
alignment = C2HS.alignment
513
peekElemOff = C2HS.peekElemOff
514
pokeElemOff = C2HS.pokeElemOff
515
peekByteOff = C2HS.peekByteOff
516
pokeByteOff = C2HS.pokeByteOff
519
instance Storable CLDouble where
522
C2HS.poke (castPtr addr) v
523
return (addr `plusPtr` sizeof v)
525
v <- C2HS.peek (castPtr addr)
526
return (v, addr `plusPtr` sizeof v)
528
alignment = C2HS.alignment
529
peekElemOff = C2HS.peekElemOff
530
pokeElemOff = C2HS.pokeElemOff
531
peekByteOff = C2HS.peekByteOff
532
pokeByteOff = C2HS.pokeByteOff
538
assignOff :: Storable a => Addr -> Int -> a -> IO Addr
539
assignOff loc off val = (loc `plusAddr` off) `assign` val
542
derefOff :: Storable a => Addr -> Int -> IO (a, Addr)
543
derefOff loc off = deref (loc `plusAddr` off)
546
assign_ :: Storable a => Addr -> a -> IO ()
547
assign_ adr x = assign adr x >> return ()
550
deref_ :: Storable a => Addr -> IO a
551
deref_ = liftM fst . deref
554
assignOff_ :: Storable a => Addr -> Int -> a -> IO ()
555
assignOff_ loc x off = assignOff loc x off >> return ()
558
derefOff_ :: Storable a => Addr -> Int -> IO a
559
derefOff_ loc off = liftM fst $ derefOff loc off
562
cToChar :: CChar -> Char
563
cToChar = castCCharToChar
565
cFromChar :: Char -> CChar
566
cFromChar = castCharToCChar
569
-- original one. The latter did not require the converted type to be
570
-- an instance of `Integral' - in particular, an instance for `Char'
573
cToInt :: Integral a => a -> Int
576
cFromInt :: Integral a => Int -> a
580
cToFloat :: RealFloat a => a -> Float
581
cToFloat = cFloatConv
583
cFromFloat :: RealFloat a => Float -> a
584
cFromFloat = cFloatConv
587
cToDouble :: RealFloat a => a -> Double
588
cToDouble = cFloatConv
590
cFromDouble :: RealFloat a => Double -> a
591
cFromDouble = cFloatConv
594
-- original one. The instance `Char' for cToBool/cFromBool is no
600
class Storable a => ToAddr a where
601
stdAddr :: a -> IO Addr
609
instance ToAddr Int16
610
instance ToAddr Int32
611
instance ToAddr Word8
612
instance ToAddr Word16
613
instance ToAddr Word32
614
instance ToAddr Float
615
instance ToAddr Double
618
instance ToAddr CChar
619
instance ToAddr CSChar
620
instance ToAddr CUChar
621
instance ToAddr CShort
622
instance ToAddr CUShort
624
instance ToAddr CUInt
625
instance ToAddr CLong
626
instance ToAddr CULong
627
instance ToAddr CLLong
628
instance ToAddr CULLong
630
instance ToAddr String where
631
stdAddr = listToAddrWithMarker (toEnum 0 :: CChar) . map castCharToCChar
634
class Storable a => FromAddr a where
635
addrStdKeep :: Addr -> IO a
638
instance FromAddr Char
639
instance FromAddr Int8
640
instance FromAddr Int16
641
instance FromAddr Int32
642
instance FromAddr Word8
643
instance FromAddr Word16
644
instance FromAddr Word32
645
instance FromAddr Float
646
instance FromAddr Double
647
instance FromAddr Addr
649
instance FromAddr CChar
650
instance FromAddr CSChar
651
instance FromAddr CUChar
652
instance FromAddr CShort
653
instance FromAddr CUShort
654
instance FromAddr CInt
655
instance FromAddr CUInt
656
instance FromAddr CLong
657
instance FromAddr CULong
658
instance FromAddr CLLong
659
instance FromAddr CULLong
661
instance FromAddr String where
662
addrStdKeep = liftM (map castCCharToChar) .
663
addrWithMarkerToList (toEnum 0 :: CChar)
666
addrStd :: FromAddr a => Addr -> IO a
668
res <- addrStdKeep adr
674
ifRaise :: (a -> (b, c)) -- selector
675
-> (b -> Bool) -- test for error condition
676
-> IO a -- foreign call
677
-> (b -> String) -- produce exception message
679
ifRaise sel p op errfct = do
680
(errval, res) <- liftM sel op
682
(ioError . userError) (errfct errval)
687
ifNegRaise :: Integral i => IO i -> String -> IO Int
688
ifNegRaise op errmsg = ifRaise cToInt2 (< 0) op (const errmsg)
690
cToInt2 x = let y = cIntConv x
695
infix 8 `ifNegRaise_`
696
ifNegRaise_ :: Integral i => IO i -> String -> IO ()
697
ifNegRaise_ op errmsg = liftM (const ()) $ ifNegRaise op errmsg
699
infix 8 `ifNullRaise`
700
ifNullRaise :: IO Addr -> String -> IO Addr
701
ifNullRaise op errmsg = ifRaise (\x -> (x, x)) (== nullAddr) op (const errmsg)
705
listToAddrWithLen :: Storable a => [a] -> IO (Addr, Int)
706
listToAddrWithLen str = do
709
return (mem, length str)
713
addrWithLenToList :: Storable a => Addr -> Int -> IO [a]
714
addrWithLenToList adr len = liftM fst $ readListFromAddr len adr
719
listToAddrWithMarker :: Storable a => a -> [a] -> IO Addr
720
listToAddrWithMarker marker str =
721
liftM fst $ listToAddrWithLen (str ++ [marker])
726
addrWithMarkerToList :: (Storable a, Eq a) => a -> Addr -> IO [a]
727
addrWithMarkerToList marker adr =
729
(x, adr') <- deref adr
730
if (x == marker) then return []
732
xs <- addrWithMarkerToList marker adr'
737
instance Storable a => Storable [a] where
738
sizeof = sum . map sizeof
739
assign = writeListToAddr
740
deref = error "C2HSMarsh: Cannot generically deserialise a list!"
743
writeListToAddr :: Storable a => Addr -> [a] -> IO Addr
744
writeListToAddr adr [] = return adr
745
writeListToAddr adr (x:xs) = do
746
adr' <- adr `assign` x
747
writeListToAddr adr' xs
750
readListFromAddr :: Storable a => Int -> Addr -> IO ([a], Addr)
751
readListFromAddr 0 adr = return ([], adr)
752
readListFromAddr n adr = do
753
(x, adr') <- deref adr
754
(xs, adr'') <- readListFromAddr (n - 1) adr'
755
return (x : xs, adr'')
761
readListFromAddr' :: Storable a => Addr -> IO [(a, Addr)]
762
readListFromAddr' adr =
764
(x, adr') <- deref adr
765
xs <- unsafePerformIO $ readListFromAddr' adr'
766
return $ (x, adr') : xs
774
data Marsh a b = (IO b) :> (b -> IO a)
779
marsh1 :: (a' -> IO r) -> (Marsh a a') -> IO (r, a)
780
marsh1 f (pre :> post) =
787
marsh1_ :: (a' -> IO r) -> (Marsh a a') -> IO r
788
marsh1_ f x = liftM fst $ marsh1 f x
790
marsh2 :: (a' -> b' -> IO r)
791
-> (Marsh a a') -> (Marsh b b')
793
marsh2 f (pre1 :> post1) (pre2 :> post2) =
802
marsh2_ :: (a' -> b' -> IO c)
803
-> (Marsh a a') -> (Marsh b b')
805
marsh2_ f x y = liftM fst $ marsh2 f x y
807
marsh3 :: (a' -> b' -> c' -> IO r)
808
-> (Marsh a a') -> (Marsh b b') -> (Marsh c c')
810
marsh3 f (pre1 :> post1) (pre2 :> post2) (pre3 :> post3) =
819
return (r, (x', y', z'))
821
marsh3_ :: (a' -> b' -> c' -> IO r)
822
-> (Marsh a a') -> (Marsh b b') -> (Marsh c c')
824
marsh3_ f x y z = liftM fst $ marsh3 f x y z
836
void :: Monad m => m (a, b) -> m b
840
ref :: (ToAddr a, FromAddr a) => a -> Marsh a Addr
841
ref x = stdAddr x :> addrStd
845
toAddr :: ToAddr v => (Addr -> IO a) -> v -> IO a
846
toAddr f val = f `marsh1_` (stdAddr val :> free)
848
toAddrKeep :: ToAddr v => (Addr -> IO a) -> v -> IO a
849
toAddrKeep f val = f `marsh1_` (stdAddr val :> use)
851
toFromAddr :: (ToAddr v, FromAddr v) => (Addr -> IO a) -> v -> IO (a, v)
852
toFromAddr f val = f `marsh1` (stdAddr val :> addrStd)