1 USING: alien alien.c-types alien.data alien.accessors
2 windows.com.syntax init windows.com.syntax.private windows.com
3 continuations kernel namespaces windows.ole32 libc vocabs
4 assocs accessors arrays sequences quotations combinators math
5 words compiler.units destructors fry math.parser generalizations
6 sets specialized-arrays windows.kernel32 classes.struct ;
7 SPECIALIZED-ARRAY: void*
8 IN: windows.com.wrapper
10 TUPLE: com-wrapper < disposable callbacks vtbls ;
14 SYMBOL: +wrapped-objects+
15 +wrapped-objects+ get-global
16 [ H{ } +wrapped-objects+ set-global ]
19 SYMBOL: +live-wrappers+
20 +live-wrappers+ get-global
21 [ V{ } +live-wrappers+ set-global ]
24 SYMBOL: +vtbl-counter+
25 +vtbl-counter+ get-global
26 [ 0 +vtbl-counter+ set-global ]
29 "windows.com.wrapper.callbacks" create-vocab drop
31 : (next-vtbl-counter) ( -- n )
32 +vtbl-counter+ [ 1 + dup ] change ;
34 : com-unwrap ( wrapped -- object )
35 +wrapped-objects+ get-global at*
36 [ "invalid COM wrapping pointer" throw ] unless ;
38 : (free-wrapped-object) ( wrapped -- )
39 [ +wrapped-objects+ get-global delete-at ] keep
42 : (query-interface-cases) ( interfaces -- cases )
44 [ find-com-interface-definition family-tree [ iid>> ] map ] dip
45 1quotation [ 2array ] curry map
49 : (make-query-interface) ( interfaces -- quot )
50 (query-interface-cases)
54 void* heap-size * rot <displaced-alien> com-add-ref
55 swap 0 set-alien-cell S_OK
56 ] [ nip f swap 0 set-alien-cell E_NOINTERFACE ] if*
59 : (make-add-ref) ( interfaces -- quot )
60 length void* heap-size * '[
62 [ alien-unsigned-4 1 + dup ]
63 [ set-alien-unsigned-4 ]
67 : (make-release) ( interfaces -- quot )
68 length void* heap-size * '[
71 [ alien-unsigned-4 1 - dup ]
72 [ set-alien-unsigned-4 ]
74 dup 0 = [ swap (free-wrapped-object) ] [ nip ] if
77 : (make-iunknown-methods) ( interfaces -- quots )
78 [ (make-query-interface) ]
80 [ (make-release) ] tri
83 : (thunk) ( n -- quot )
86 [ void* heap-size neg * '[ _ swap <displaced-alien> ] ]
89 : (thunked-quots) ( quots iunknown-methods thunk -- {thunk,quot}s )
90 [ '[ @ com-unwrap ] [ swap 2array ] curry map ]
91 [ [ swap 2array ] curry map ] bi-curry bi*
94 : compile-alien-callback ( word return parameters abi quot -- word )
95 '[ _ _ _ _ alien-callback ]
96 [ [ ( -- alien ) define-declared ] pick [ call ] dip ]
97 with-compilation-unit ;
99 : (callback-word) ( function-name interface counter -- word )
100 [ name>> "::" rot 3append "-callback-" ] dip number>string 3append
101 "windows.com.wrapper.callbacks" create-word ;
103 : (finish-thunk) ( param-count thunk quot -- thunked-quot )
104 [ [ drop [ ] ] [ swap 1 - '[ _ _ ndip ] ] if-empty ]
107 : (make-interface-callbacks) ( interface quots iunknown-methods n -- words )
108 (thunk) (thunked-quots)
109 swap [ find-com-interface-definition family-tree-functions ]
110 keep (next-vtbl-counter) '[
112 [ name>> _ _ (callback-word) ]
113 [ return>> ] [ parameter-types>> dup length ] tri
115 first2 (finish-thunk)
117 stdcall swap compile-alien-callback
120 : (make-callbacks) ( implementations -- sequence )
121 dup keys (make-iunknown-methods)
122 [ [ first2 ] 2dip swap (make-interface-callbacks) ]
125 : (malloc-wrapped-object) ( wrapper -- wrapped-object )
126 vtbls>> length void* heap-size *
127 [ ulong heap-size + malloc ] keep
128 [ [ 1 ] 2dip set-alien-unsigned-4 ] [ drop ] 2bi ;
130 : (callbacks>vtbl) ( callbacks -- vtbl )
131 [ execute( -- callback ) ] void*-array{ } map-as malloc-byte-array ;
132 : (callbacks>vtbls) ( callbacks -- vtbls )
133 [ (callbacks>vtbl) ] map ;
135 : (allocate-wrapper) ( wrapper -- )
136 dup callbacks>> (callbacks>vtbls) >>vtbls
139 : com-startup-hook ( -- )
140 +live-wrappers+ get-global [ (allocate-wrapper) ] each
141 H{ } +wrapped-objects+ set-global ;
143 STARTUP-HOOK: com-startup-hook
147 : allocate-wrapper ( wrapper -- )
148 [ (allocate-wrapper) ]
149 [ +live-wrappers+ get adjoin ] bi ;
151 : <com-wrapper> ( implementations -- wrapper )
152 com-wrapper new-disposable swap (make-callbacks) >>callbacks
153 dup allocate-wrapper ;
155 M: com-wrapper dispose*
156 [ [ free ] each f ] change-vtbls
157 +live-wrappers+ get-global remove! drop ;
159 : com-wrap ( object wrapper -- wrapped-object )
160 [ vtbls>> ] [ (malloc-wrapped-object) ] bi
161 [ over length void* <c-direct-array> 0 swap copy ] keep
162 [ +wrapped-objects+ get-global set-at ] keep ;