3 (define-foreign-type g-boxed-foreign-type
()
5 :accessor g-boxed-foreign-info
6 :initform
(error "info must be specified"))
7 (free-from-foreign :initarg
:free-from-foreign
9 :accessor g-boxed-foreign-free-from-foreign
)
10 (free-to-foreign :initarg
:free-to-foreign
12 :accessor g-boxed-foreign-free-to-foreign
)
13 (for-callback :initarg
:for-callback
15 :accessor g-boxed-foreign-for-callback
))
16 (:actual-type
:pointer
))
18 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
19 (defstruct g-boxed-info
23 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
24 (defun get-g-boxed-foreign-info (name)
25 (get name
'g-boxed-foreign-info
)))
27 (define-parse-method g-boxed-foreign
(name &key free-from-foreign free-to-foreign for-callback
)
28 (let ((info (get-g-boxed-foreign-info name
)))
29 (assert info nil
"Unknown foreign GBoxed type ~A" name
)
30 (make-instance 'g-boxed-foreign-type
32 :free-from-foreign free-from-foreign
33 :free-to-foreign free-to-foreign
34 :for-callback for-callback
)))
36 (eval-when (:load-toplevel
:compile-toplevel
:execute
)
37 (defstruct (g-boxed-cstruct-wrapper-info (:include g-boxed-info
))
41 (defmacro define-g-boxed-cstruct
(name cstruct-name g-type-name
&body slots
)
44 ,@(iter (for (name type
&key initarg
) in slots
)
45 (collect (list name initarg
))))
46 (defcstruct ,cstruct-name
47 ,@(iter (for (name type
&key initarg
) in slots
)
48 (collect `(,name
,type
))))
49 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
50 (setf (get ',name
'g-boxed-foreign-info
)
51 (make-g-boxed-cstruct-wrapper-info :name
',name
53 :cstruct
',cstruct-name
54 :slots
',(iter (for (name type
&key initarg
) in slots
)
57 (define-g-boxed-cstruct gdk-rectangle gdk-rectangle-cstruct
"GdkRectangle"
60 (width :int
:initarg
0)
61 (height :int
:initarg
0))
63 (defgeneric create-temporary-native
(type proxy
)
64 (:documentation
"Creates a native structure (or passes a pointer to copy contained in PROXY)
65 that contains the same data that the PROXY contains and returns a pointer to it.
67 This call is always paired by call to FREE-TEMPORARY-NATIVE and calls may be nested."))
69 (defgeneric free-temporary-native
(type proxy native-ptr
)
70 (:documentation
"Frees the native structure that was previously created
71 by CREATE-TEMPORARY-NATIVE for the same PROXY.
73 Also reads data from native structure pointer to by NATIVE-PTR
74 and sets the PROXY to contain the same data.
76 This call is always paired by call to CREATE-TEMPORARY-NATIVE and calls may be nested."))
78 (defgeneric create-proxy-for-native
(type native-ptr
)
79 (:documentation
"Creates a proxy that is initialized by data contained in native
80 structured pointed to by NATIVE-PTR.
82 Created proxy should not be linked to NATIVE-PTR and should have
83 indefinite lifetime (until garbage collector collects it). Specifically,
84 if proxy need a pointer to native structure, it should make a copy of
87 If proxy requires finalization, finalizers should be added."))
89 (defgeneric create-reference-proxy
(type native-ptr
)
90 (:documentation
"Creates a reference proxy for a native structure pointed to by NATIVE-PTR.
92 Reference proxy's lifetime is bound to duration of a callback. When the
93 callback returns the reference proxy is declared invalid and operations on it are errors.
95 This call is always paired by call to FREE-REFERENCE-PROXY and calls will not nest."))
97 (defgeneric free-reference-proxy
(type proxy native-ptr
)
98 (:documentation
"Frees a reference proxy PROXY previously created by call to
99 CREATE-REFERENCE-PROXY. This call should ensure that all changes on PROXY are
100 reflected in native structure pointed to by NATIVE-PTR.
102 After a call to FREE-REFERENCE-PROXY, PROXY is declared invalid and using it is an error,
103 operations on it should signal erros.
105 This call is always paired by call to CREATE-REFERENCE-PROXY."))
107 (defmethod create-temporary-native ((type g-boxed-cstruct-wrapper-info
) proxy
)
108 (format t
"create-temporary-native~%")
109 (let* ((native-structure-type (g-boxed-cstruct-wrapper-info-cstruct type
))
110 (native-structure (foreign-alloc native-structure-type
)))
111 (iter (for slot in
(g-boxed-cstruct-wrapper-info-slots type
))
112 (setf (foreign-slot-value native-structure native-structure-type slot
)
113 (slot-value proxy slot
)))
116 (defmethod free-temporary-native ((type g-boxed-cstruct-wrapper-info
) proxy native-structure
)
117 (format t
"free-temporary-native~%")
118 (let ((native-structure-type (g-boxed-cstruct-wrapper-info-cstruct type
)))
119 (iter (for slot in
(g-boxed-cstruct-wrapper-info-slots type
))
120 (setf (slot-value proxy slot
)
121 (foreign-slot-value native-structure native-structure-type slot
))))
122 (foreign-free native-structure
))
124 (defmethod create-proxy-for-native ((type g-boxed-cstruct-wrapper-info
) native-structure
)
125 (format t
"create-proxy-for-native~%")
126 (let* ((native-structure-type (g-boxed-cstruct-wrapper-info-cstruct type
))
127 (proxy (make-instance (g-boxed-info-name type
))))
128 (iter (for slot in
(g-boxed-cstruct-wrapper-info-slots type
))
129 (setf (slot-value proxy slot
)
130 (foreign-slot-value native-structure native-structure-type slot
)))
133 (defmethod create-reference-proxy ((type g-boxed-cstruct-wrapper-info
) native-structure
)
134 (format t
"create-reference-proxy~%")
135 (create-proxy-for-native type native-structure
))
137 (defmethod free-reference-proxy ((type g-boxed-cstruct-wrapper-info
) proxy native-structure
)
138 (format t
"free-reference-proxy~%")
139 (let ((native-structure-type (g-boxed-cstruct-wrapper-info-cstruct type
)))
140 (iter (for slot in
(g-boxed-cstruct-wrapper-info-slots type
))
141 (setf (foreign-slot-value native-structure native-structure-type slot
)
142 (slot-value proxy slot
)))))
144 (defmethod translate-to-foreign (proxy (type g-boxed-foreign-type
))
146 (let* ((info (g-boxed-foreign-info type
)))
147 (values (create-temporary-native info proxy
) proxy
))
150 (defmethod free-translated-object (native-structure (type g-boxed-foreign-type
) proxy
)
152 (free-temporary-native (g-boxed-foreign-info type
) proxy native-structure
)))
154 (defmethod translate-from-foreign (native-structure (type g-boxed-foreign-type
))
155 (unless (null-pointer-p native-structure
)
156 (let* ((info (g-boxed-foreign-info type
)))
158 ((g-boxed-foreign-for-callback type
)
159 (create-reference-proxy info native-structure
))
160 ((or (g-boxed-foreign-free-to-foreign type
)
161 (g-boxed-foreign-free-from-foreign type
))
162 (error "Feature not yet handled"))
163 (t (create-proxy-for-native info native-structure
))))))
165 (defmethod cleanup-translated-object-for-callback ((type g-boxed-foreign-type
) proxy native-structure
)
166 (unless (null-pointer-p native-structure
)
167 (free-reference-proxy (g-boxed-foreign-info type
) proxy native-structure
)))
169 (defmethod has-callback-cleanup ((type g-boxed-foreign-type
))
172 (defcallback incf-rectangle
:void
((rectangle (g-boxed-foreign gdk-rectangle
:for-callback t
))
174 (incf (gdk-rectangle-x rectangle
) delta
)
175 (incf (gdk-rectangle-y rectangle
) delta
)
176 (incf (gdk-rectangle-width rectangle
) delta
)
177 (incf (gdk-rectangle-height rectangle
) delta
)
178 (format t
"~A~%" rectangle
))
180 (defun do-incf-rect (r &optional
(delta 1))
181 (foreign-funcall-pointer (callback incf-rectangle
) ()
182 (g-boxed-foreign gdk-rectangle
) r
187 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
188 (defstruct (g-boxed-opaque-wrapper-info (:include g-boxed-info
))
191 (defclass g-boxed-opaque
()
192 ((pointer :initarg
:pointer
194 :accessor g-boxed-opaque-pointer
)))
196 (defmethod create-temporary-native ((type g-boxed-opaque-wrapper-info
) proxy
)
197 (declare (ignore type
))
198 (g-boxed-opaque-pointer proxy
))
200 (defmethod free-temporary-native ((type g-boxed-opaque-wrapper-info
) proxy native-structure
)
201 (declare (ignore type proxy native-structure
)))
203 (defmethod create-reference-proxy ((type g-boxed-opaque-wrapper-info
) native-structure
)
204 (make-instance (g-boxed-info-g-type type
) :pointer native-structure
))
206 (defmethod free-reference-proxy ((type g-boxed-opaque-wrapper-info
) proxy native-structure
)
207 (declare (ignore type native-structure
))
208 (setf (g-boxed-opaque-pointer proxy
) nil
))
210 (defmethod create-proxy-for-native ((type g-boxed-opaque-wrapper-info
) native-structure
)
211 (let* ((g-type (g-boxed-info-g-type type
))
212 (native-copy (g-boxed-copy g-type native-structure
)))
213 (flet ((finalizer () (g-boxed-free g-type native-copy
)))
214 (let ((proxy (make-instance (g-boxed-opaque-wrapper-info-g-type type
) :pointer native-copy
)))
215 (tg:finalize proxy
#'finalizer
)
218 (defmacro define-g-boxed-opaque
(name g-type-name
&key
219 (alloc (error "Alloc must be specified")))
220 (let ((native-copy (gensym "NATIVE-COPY-"))
221 (instance (gensym "INSTANCE-"))
222 (finalizer (gensym "FINALIZER-")))
223 `(progn (defclass ,name
(g-boxed-opaque) ())
224 (defmethod initialize-instance :after
((,instance
,name
) &key
&allow-other-keys
)
225 (unless (g-boxed-opaque-pointer ,instance
)
226 (let ((,native-copy
,alloc
))
227 (flet ((,finalizer
() (g-boxed-free ,g-type-name
,native-copy
)))
228 (setf (g-boxed-opaque-pointer ,instance
) ,native-copy
)
229 (finalize ,instance
#',finalizer
)))))
230 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
231 (setf (get ',name
'g-boxed-foreign-info
)
232 (make-g-boxed-opaque-wrapper-info :name
',name
233 :g-type
,g-type-name
))))))
235 (define-g-boxed-opaque gtk-tree-path
"GtkTreePath"
236 :alloc
(let* ((native-structure (gtk-tree-path-new))
237 (native-copy (g-boxed-copy "GtkTreePath" native-structure
)))
238 (gtk-tree-path-free native-structure
)
241 (defcfun gtk-tree-path-new
:pointer
)
243 (defcfun gtk-tree-path-free
:void
244 (gtk-tree-path :pointer
))
246 (defcfun gtk-tree-path-copy
:pointer
247 (gtk-tree-path :pointer
))
249 (defcfun (%gtk-tree-path-get-depth
"gtk_tree_path_get_depth") :int
250 (path (g-boxed-foreign gtk-tree-path
)))
252 (defcfun (%gtk-tree-path-get-indices
"gtk_tree_path_get_indices") (:pointer
:int
)
253 (path (g-boxed-foreign gtk-tree-path
)))
255 (defcfun gtk-tree-path-append-index
:void
256 (path (g-boxed-foreign gtk-tree-path
))
259 (defun tree-path-get-indices (path)
260 (let ((n (%gtk-tree-path-get-depth path
))
261 (indices (%gtk-tree-path-get-indices path
)))
264 collect
(mem-aref indices
:int i
))))