summaryrefslogtreecommitdiff
path: root/ghc/lib/glaExts/Foreign.lhs
blob: 81abc4f13dc0857458e42a432491d27e05591f16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
%
% (c) The AQUA Project, Glasgow University, 1994-1996
%

\section[Foreign]{Module @Foreign@}

\begin{code}
{-# OPTIONS -fno-implicit-prelude #-}

module Foreign (
	module Foreign,
	ForeignObj(..),
	Addr, Word
   ) where

import STBase
import ArrBase
import PrelBase
import GHC
\end{code}


%*********************************************************
%*							*
\subsection{Classes @CCallable@ and @CReturnable@}
%*							*
%*********************************************************

\begin{code}
class CCallable   a
class CReturnable a

instance CCallable Char
instance CCallable   Char#
instance CReturnable Char

instance CCallable   Int
instance CCallable   Int#
instance CReturnable Int

-- DsCCall knows how to pass strings...
instance CCallable   [Char]

instance CCallable   Float
instance CCallable   Float#
instance CReturnable Float

instance CCallable   Double
instance CCallable   Double#
instance CReturnable Double

instance CCallable Addr
instance CCallable Addr#
instance CReturnable Addr

instance CCallable Word
instance CCallable Word#
instance CReturnable Word

-- Is this right?
instance CCallable (MutableByteArray s ix)
instance CCallable (MutableByteArray# s)

instance CCallable (ByteArray ix)
instance CCallable ByteArray#

instance CReturnable () -- Why, exactly?
\end{code}


%*********************************************************
%*							*
\subsection{Type @ForeignObj@ and its operations}
%*							*
%*********************************************************

\begin{code}
--Defined in PrelBase: data ForeignObj = ForeignObj ForeignObj#
instance CCallable ForeignObj
instance CCallable ForeignObj#

eqForeignObj    :: ForeignObj  -> ForeignObj -> Bool
makeForeignObj  :: Addr        -> Addr       -> PrimIO ForeignObj
writeForeignObj :: ForeignObj  -> Addr       -> PrimIO ()

{- derived op - attaching a free() finaliser to a malloc() allocated reference. -}
makeMallocPtr   :: Addr        -> PrimIO ForeignObj

makeForeignObj (A# obj) (A# finaliser) = ST ( \ (S# s#) ->
    case makeForeignObj# obj finaliser s# of
      StateAndForeignObj# s1# fo# -> (ForeignObj fo#, S# s1#))

writeForeignObj (ForeignObj fo#) (A# datum#) = ST ( \ (S# s#) ->
    case writeForeignObj# fo# datum# s# of { s1# -> ((), S# s1#) } )

makeMallocPtr a = makeForeignObj a (``&free''::Addr)

eqForeignObj mp1 mp2
  = unsafePerformPrimIO (_ccall_ eqForeignObj mp1 mp2) /= (0::Int)

instance Eq ForeignObj where 
    p == q = eqForeignObj p q
    p /= q = not (eqForeignObj p q)
\end{code}


%*********************************************************
%*							*
\subsection{Type @StablePtr@ and its operations}
%*							*
%*********************************************************

\begin{code}
#ifndef __PARALLEL_HASKELL__
data StablePtr a = StablePtr (StablePtr# a)
instance CCallable   (StablePtr a)
instance CCallable   (StablePtr# a)
instance CReturnable (StablePtr a)

-- Nota Bene: it is important {\em not\/} to inline calls to
-- @makeStablePtr#@ since the corresponding macro is very long and we'll
-- get terrible code-bloat.

makeStablePtr  :: a -> PrimIO (StablePtr a)
deRefStablePtr :: StablePtr a -> PrimIO a
freeStablePtr  :: StablePtr a -> PrimIO ()
performGC      :: PrimIO ()

{-# INLINE deRefStablePtr #-}
{-# INLINE freeStablePtr #-}
{-# INLINE performGC #-}

makeStablePtr f = ST $ \ (S# rw1#) ->
    case makeStablePtr# f rw1# of
      StateAndStablePtr# rw2# sp# -> (StablePtr sp#, S# rw2#)

deRefStablePtr (StablePtr sp#) = ST $ \ (S# rw1#) ->
    case deRefStablePtr# sp# rw1# of
      StateAndPtr# rw2# a -> (a, S# rw2#)

freeStablePtr sp = _ccall_ freeStablePointer sp

performGC = _ccall_GC_ StgPerformGarbageCollection

#endif /* !__PARALLEL_HASKELL__ */
\end{code}

%*********************************************************
%*							*
\subsection{Ghastly return types}
%*							*
%*********************************************************

\begin{code}
#ifndef __PARALLEL_HASKELL__
data StateAndStablePtr# s a = StateAndStablePtr# (State# s) (StablePtr# a)
#endif
data StateAndForeignObj# s  = StateAndForeignObj# (State# s) ForeignObj#
\end{code}