1 USING: alien alien.c-types windows.com.syntax
2 windows.com.syntax.private windows.com continuations kernel
3 namespaces windows.ole32 libc vocabs assocs accessors arrays
4 sequences quotations combinators math words compiler.units
5 destructors fry math.parser generalizations ;
6 IN: windows.com.wrapper
8 TUPLE: com-wrapper vtbls disposed ;
12 SYMBOL: +wrapped-objects+
13 +wrapped-objects+ get-global
14 [ H{ } +wrapped-objects+ set-global ]
17 SYMBOL: +vtbl-counter+
18 +vtbl-counter+ get-global
19 [ 0 +vtbl-counter+ set-global ]
22 "windows.com.wrapper.callbacks" create-vocab drop
24 : (next-vtbl-counter) ( -- n )
25 +vtbl-counter+ [ 1+ dup ] change ;
27 : com-unwrap ( wrapped -- object )
28 +wrapped-objects+ get-global at*
29 [ "invalid COM wrapping pointer" throw ] unless ;
31 : (free-wrapped-object) ( wrapped -- )
32 [ +wrapped-objects+ get-global delete-at ] keep
35 : (query-interface-cases) ( interfaces -- cases )
37 [ find-com-interface-definition family-tree [ iid>> ] map ] dip
38 1quotation [ 2array ] curry map
42 : (make-query-interface) ( interfaces -- quot )
43 (query-interface-cases)
45 swap 16 memory>byte-array
48 "void*" heap-size * rot <displaced-alien> com-add-ref
49 0 rot set-void*-nth S_OK
50 ] [ nip f 0 rot set-void*-nth E_NOINTERFACE ] if*
53 : (make-add-ref) ( interfaces -- quot )
54 length "void*" heap-size * '[
55 , swap <displaced-alien>
57 1+ [ 0 rot set-ulong-nth ] keep
60 : (make-release) ( interfaces -- quot )
61 length "void*" heap-size * '[
62 , over <displaced-alien>
64 1- [ 0 rot set-ulong-nth ] keep
65 dup zero? [ swap (free-wrapped-object) ] [ nip ] if
68 : (make-iunknown-methods) ( interfaces -- quots )
69 [ (make-query-interface) ]
71 [ (make-release) ] tri
74 : (thunk) ( n -- quot )
77 [ "void*" heap-size neg * '[ , swap <displaced-alien> ] ]
80 : (thunked-quots) ( quots iunknown-methods thunk -- {thunk,quot}s )
81 [ '[ , '[ @ com-unwrap ] [ swap 2array ] curry map ] ]
82 [ '[ , [ swap 2array ] curry map ] ] bi bi*
85 : compile-alien-callback ( word return parameters abi quot -- alien )
86 '[ , , , , alien-callback ]
87 [ [ (( -- alien )) define-declared ] pick slip ]
91 : (byte-array-to-malloced-buffer) ( byte-array -- alien )
92 [ byte-length malloc ] [ over byte-array>memory ] bi ;
94 : (callback-word) ( function-name interface-name counter -- word )
95 [ "::" rot 3append "-callback-" ] dip number>string 3append
96 "windows.com.wrapper.callbacks" create ;
98 : (finish-thunk) ( param-count thunk quot -- thunked-quot )
99 [ dup empty? [ 2drop [ ] ] [ swap 1- '[ , , ndip ] ] if ]
102 : (make-vtbl) ( interface-name quots iunknown-methods n -- vtbl )
103 (thunk) (thunked-quots)
104 swap [ find-com-interface-definition family-tree-functions ]
105 keep (next-vtbl-counter) '[
107 [ name>> , , (callback-word) ]
114 first2 (finish-thunk)
116 "stdcall" swap compile-alien-callback
117 ] 2map >c-void*-array
118 (byte-array-to-malloced-buffer) ;
120 : (make-vtbls) ( implementations -- vtbls )
121 dup [ first ] map (make-iunknown-methods)
122 [ >r >r first2 r> r> swap (make-vtbl) ] curry map-index ;
124 : (malloc-wrapped-object) ( wrapper -- wrapped-object )
125 vtbls>> length "void*" heap-size *
126 [ "ulong" heap-size + malloc ] keep
127 over <displaced-alien>
128 1 0 rot set-ulong-nth ;
132 : <com-wrapper> ( implementations -- wrapper )
133 (make-vtbls) f com-wrapper boa ;
135 M: com-wrapper dispose*
136 vtbls>> [ free ] each ;
138 : com-wrap ( object wrapper -- wrapped-object )
139 [ vtbls>> ] [ (malloc-wrapped-object) ] bi
140 [ [ set-void*-nth ] curry each-index ] keep
141 [ +wrapped-objects+ get-global set-at ] keep ;