Removed old Gboxed code
authorDmitry Kalyanov <Kalyanov.Dmitry@gmail.com>
Fri, 7 Aug 2009 22:29:00 +0000 (02:29 +0400)
committerDmitry Kalyanov <Kalyanov.Dmitry@gmail.com>
Fri, 7 Aug 2009 22:29:00 +0000 (02:29 +0400)
glib/gobject.foreign-gboxed.lisp [deleted file]

diff --git a/glib/gobject.foreign-gboxed.lisp b/glib/gobject.foreign-gboxed.lisp
deleted file mode 100644 (file)
index b196cab..0000000
+++ /dev/null
@@ -1,502 +0,0 @@
-(in-package :gobject)
-
-(defun ensure-list (thing)
-  (if (listp thing) thing (list thing)))
-
-(defun slot->cstruct-slot (slot)
-  (destructuring-bind (name type &key &allow-other-keys) slot
-    `(,name ,type)))
-
-(defun slot->slot-name (slot)
-  (destructuring-bind (name type &key &allow-other-keys) slot
-    (declare (ignore type))
-    name))
-
-(defun cstruct-definition (name slots)
-  `(defcstruct ,name ,@(mapcar #'slot->cstruct-slot slots)))
-
-(defun maybe-unlist (thing)
-  (if (or (not (listp thing)) (cdr thing))
-      thing
-      (car thing)))
-
-(defun slot->struct-slot (slot)
-  (destructuring-bind (name type &key initform &allow-other-keys) slot
-    (declare (ignore type))
-    (maybe-unlist `(,name ,@(when initform (list initform))))))
-
-(defun struct-definition (name superclass slots)
-  `(defstruct ,@(if superclass
-                    (list `(,name (:include ,superclass)))
-                    (list name))
-     ,@(mapcar #'slot->struct-slot slots)))
-
-(define-foreign-type g-boxed-pointer-type ()
-  ((name :accessor g-boxed-pointer-type-name :initarg :name)
-   (outp :accessor g-boxed-pointer-type-outp :initarg :outp)))
-
-(define-parse-method g-boxed-ptr (name &optional (type :in))
-  (make-instance 'g-boxed-pointer-type :name name :actual-type :pointer :outp (ecase type
-                                                                                (:in nil)
-                                                                                (:in-out t))))
-
-(defmethod translate-from-foreign (value (type g-boxed-pointer-type))
-  (unless (null-pointer-p value)
-    (parse-g-boxed value (g-boxed-pointer-type-name type))))
-
-(defmethod translate-to-foreign (value (type g-boxed-pointer-type))
-  (if value
-      (let ((ptr (foreign-alloc (boxed-c-structure-name (g-boxed-pointer-type-name type)))))
-        (real-unparse-g-boxed ptr value)
-        (values ptr value))
-      (null-pointer)))
-
-(defmethod free-translated-object (ptr (type g-boxed-pointer-type) param)
-  (unless (null-pointer-p ptr)
-    (when (g-boxed-pointer-type-outp type)
-      (let ((original-object param)
-            (new-real-name (g-boxed-real-name ptr (g-boxed-pointer-type-name type))))
-        (if (eq new-real-name (type-of original-object))
-            (real-parse-g-boxed ptr original-object)
-            (error "Type has changed!")))))
-  (foreign-free ptr))
-
-(defmethod expand-to-foreign-dyn (value var body (type g-boxed-pointer-type))
-  (let ((value-var (gensym)))
-    `(with-foreign-object (,var ',(boxed-c-structure-name (g-boxed-pointer-type-name type)))
-       (let ((,value-var ,value))
-         (when ,value-var
-           (real-unparse-g-boxed ,var ,value-var))
-         (if (null ,value-var)
-             (let ((,var (null-pointer)))
-               ,@body)
-             (progn ,@body
-                    ,@(when (g-boxed-pointer-type-outp type)
-                            (list `(when ,value-var
-                                     (let ((new-real-name (g-boxed-real-name ,var ',(g-boxed-pointer-type-name type))))
-                                       (if (eq new-real-name (type-of ,value-var))
-                                           (real-parse-g-boxed ,var ,value-var)
-                                           (error "Type has changed from ~A to ~A" (type-of ,value-var) new-real-name))))))))))))
-
-(define-foreign-type g-boxed-inline-type ()
-  ((name :accessor g-boxed-inline-type :initarg :name)))
-
-(define-parse-method g-boxed-inline (name)
-  (make-instance 'g-boxed-inline-type :name name :actual-type name))
-
-(defgeneric real-parse-g-boxed (pointer object))
-(defgeneric real-unparse-g-boxed (pointer object))
-
-(defun parse-g-boxed (pointer name)
-  (unless (null-pointer-p pointer)
-    (let* ((real-name (g-boxed-real-name pointer name))
-           (object (make-instance real-name)))
-      (real-parse-g-boxed pointer object)
-      object)))
-
-(defun boxed-alloc (type alloc-type)
-  (ecase alloc-type
-    (:cffi (foreign-alloc type))
-    (:boxed (let ((pointer (foreign-alloc type)))
-              (prog1 (g-boxed-copy (g-type-from-name (boxed-type-gname type)) pointer)
-                (foreign-free pointer))))))
-
-(defun g-boxed->cstruct (object &key (alloc-type :cffi))
-  (let ((pointer (boxed-alloc (type-of object) alloc-type)))
-    (real-unparse-g-boxed pointer object)
-    pointer))
-
-(defun g-boxed-real-name (pointer name)
-  (or (loop
-         for (sub-name slot values) in (get name 'boxed-dispatch)
-         do (debugf "Checking ~A ~A ~A against ~A.~A = ~A~%" sub-name slot values name slot (foreign-slot-value pointer name slot)) 
-         when (member (foreign-slot-value pointer name slot) values :test 'equalp)
-         return (g-boxed-real-name pointer sub-name))
-      name))
-
-(defun slot->slot-parser (class-name pointer-var slot)
-  (destructuring-bind (slot-name slot-type &key parser &allow-other-keys) slot
-    (cond
-      (parser
-       `(setf ,slot-name (funcall ,parser ',class-name ,pointer-var)))
-      ((and (listp slot-type) (eq 'g-boxed-inline (first slot-type)))
-       `(setf ,slot-name (parse-g-boxed (foreign-slot-pointer ,pointer-var ',class-name ',slot-name) ',(second slot-type))))
-      (t
-       `(setf ,slot-name (foreign-slot-value ,pointer-var ',class-name ',slot-name))))))
-
-(defun parse-method-definition (name slots)
-  (let ((slot-names (mapcar #'slot->slot-name slots)))
-    `(defmethod real-parse-g-boxed (pointer (object ,name))
-       (with-slots (,@slot-names) object
-         ,@(mapcar (lambda (slot) (slot->slot-parser name 'pointer slot)) slots)))))
-
-(defun slot->slot-unparser (class-name pointer-var slot object)
-  (destructuring-bind (slot-name slot-type &key unparser &allow-other-keys) slot
-    (cond
-      (unparser
-       `(funcall ,unparser ',class-name ,pointer-var ,object))
-      ((and (listp slot-type) (eq 'g-boxed-inline (first slot-type)))
-       `(real-unparse-g-boxed (foreign-slot-pointer ,pointer-var ',class-name ',slot-name) ,slot-name))
-      (t
-       `(setf (foreign-slot-value ,pointer-var ',class-name ',slot-name) ,slot-name)))))
-  
-(defun unparse-method-definition (name slots)
-  (let ((slot-names (mapcar #'slot->slot-name slots)))
-    `(defmethod real-unparse-g-boxed (pointer (object ,name))
-       (with-slots (,@slot-names) object
-         ,@(mapcar (lambda (slot) (slot->slot-unparser name 'pointer slot 'object)) slots)))))
-
-(defun slot->export-accessor (class-name slot)
-  (destructuring-bind (slot-name slot-type &key &allow-other-keys) slot
-    (declare (ignore slot-type))
-    (let ((accessor-name (intern (format nil "~A-~A" (symbol-name class-name) (symbol-name slot-name))
-                                 (symbol-package class-name))))
-      `(export ',accessor-name (symbol-package ',accessor-name)))))
-
-(defun struct-constructor-name (name)
-  (intern (format nil "MAKE-~A" (symbol-name name)) (symbol-package name)))
-
-(defun get-g-boxed-direct-subclasses (name)
-  (mapcar (lambda (spec) (destructuring-bind (name slot values) spec
-                           (declare (ignore slot values))
-                           name))
-          (get name 'boxed-dispatch)))
-
-(defun map-append (f &rest lists)
-  (reduce #'append (apply #'mapcar f lists)))
-
-(defun get-g-boxed-all-subclasses (name)
-  (cons name
-        (map-append #'get-g-boxed-all-subclasses (get-g-boxed-direct-subclasses name))))
-
-(defun get-g-boxed-completed-c-definition (name union-name)
-  `(defcunion ,union-name
-     ,@(mapcar (lambda (sub-name)
-                 `(,sub-name ,sub-name))
-               (get-g-boxed-all-subclasses name))))
-
-(defun g-boxed-root (name)
-  (if (get name 'superclass)
-      (g-boxed-root (get name 'superclass))
-      name))
-
-(defmacro update-g-boxed-root-c-class (name)
-  (when (get name 'c-name)
-    (get-g-boxed-completed-c-definition (g-boxed-root name) (get name 'c-name))))
-
-(defmacro define-g-boxed-class (g-name-and-c-name name (&optional superclass-and-dispatch (export t)) &body slots)
-  "Defines the class corresponding to GBoxed type. Used only for structures that are passed (semantically) by value. E.g., GdkEvent.
-Single inheritance of classes is supported (and is used for definining different sub-types of GdkEvent). Decision of which class to use for a given C structure is made based on values of certain slots (see arguments @code{dispatch-slot} and @code{dispatch-values}).
-
-Example:
-
-@begin{pre}
-\(define-g-boxed-class (\"GdkEvent\" event-struct) event ()
-  (type event-type)
-  (window (g-object gdk-window))
-  (send-event (:boolean :int8)))
-
-\(define-g-boxed-class nil event-button ((event type (:button-press :2button-press :3button-press :button-release)))
-  (time :uint32)
-  (x :double)
-  (y :double)
-  (axes (fixed-array :double 2))
-  (state :uint)
-  (button :uint)
-  (device (g-object device))
-  (x-root :double)
-  (y-root :double))
-
-\(define-g-boxed-class \"GdkColor\" color ()
-  (pixel :uint32 :initform 0)
-  (red :uint16 :initform 0)
-  (green :uint16 :initform 0)
-  (blue :uint16 :initform 0))
-@end{pre}
-@arg[g-name-and-c-name]{@code{NIL} or list @code{(&optional g-name c-name)}; g-name is the GObject type name and c-name is the name of generated CFFI C structure.}
-@arg[name]{a symbol; name of the structure (defstruct) that is defined}
-@arg[superclass-and-dispatch]{@code{NIL} or list @code{(&optional superclass dispatch-slot dispatch-values)}}
-@arg[superclass]{a symbol denoting the superclass of the class being defined}
-@arg[dispatch-slot]{a symbol denoting the slot of the superclass that identifies the \"real\" class}
-@arg[dispatch-values]{a value or a list of values of @code{dispatch-slot} of @code{superclass} that correspond to the class being defined}
-@arg[export]{a boolean; defines whether all related symbols (@code{name} and generated slot accessors) should be exported from the current package}
-@arg[slots]{a list of slots; each slot is defined by list @code{(name type &key initform parser unparser)}.
-@begin{itemize}
-@item{@code{name} is the name of a slot}
-@item{@code{type} is a CFFI type of a slot}
-@item{@code{initform} is an expression that is the iniform of a slot in generated @code{defstruct}; used when the lisp code creates the object.}
-@item{@code{parser} is a function designator for a slot parser function (if a slot parsing depends on other slots of a structure; custom slot parsing is better implemented with CFFI foreign types). Slot parser function is a function that accepts two arguments: name of a slot and a pointer to C structure and returns the value of a slot}
-@item{@code{unparser} is a function designator for a slot unparser function. Slot unparsing function is a function that accepts three arguments: name of a slot, pointer to a C structure and a value of a slot. It should assign the slot value to a C structure.}
-@end{itemize}}"
-  (destructuring-bind (&optional g-name c-name) (ensure-list g-name-and-c-name)
-    (destructuring-bind (&optional superclass dispatch-slot dispatch-values) superclass-and-dispatch
-      (let* ((superclass-slots (get superclass 'boxed-combined-slots))
-             (combined-slots (append superclass-slots slots)))
-        
-        (setf c-name (or c-name (gensym "C-UNION-")))
-        `(progn ,(cstruct-definition name combined-slots)
-                ,(struct-definition name superclass slots)
-                ,(parse-method-definition name combined-slots)
-                ,(unparse-method-definition name combined-slots)
-                (eval-when (:load-toplevel :compile-toplevel :execute)
-                  (setf (get ',name 'boxed-slots) ',slots
-                        (get ',name 'boxed-combined-slots) ',combined-slots
-                        (get ',name 'superclass) ',superclass
-                        (get ',name 'c-name) (or (get ',name 'c-name) ',c-name))
-                  ,@(when superclass
-                          (list `(pushnew '(,name ,dispatch-slot ,(ensure-list dispatch-values)) (get ',superclass 'boxed-dispatch) :test 'equalp))))
-                (update-g-boxed-root-c-class ,name)
-                ,@(when g-name
-                        (list `(register-boxed-type ,g-name ',name)))
-                ,@(when export
-                        (append (list `(export ',name (symbol-package ',name))
-                                      `(export ',(struct-constructor-name name) (symbol-package ',(struct-constructor-name name))))
-                                (mapcar (lambda (slot) (slot->export-accessor name slot)) slots))))))))
-
-(defun boxed-c-structure-name (name)
-  (get (g-boxed-root name) 'c-name))
-
-(defclass g-boxed-ref ()
-  ((pointer :accessor pointer :initarg :pointer))
-  (:documentation "Class corresponding to GBoxed objects that are passed by reference to C structure rather than by value.
-
-Instances of this class are collected by garbage collector. Each object has an owner: lisp code or C code. If owner is the lisp code then the corresponding C structure will be freed when the object is collected. Is the owner is the C code, the C structure lifetime is not connected with the lifetime of the object: it may be freed before or after the object becomes collected. If the owner if C code, lisp code must be careful not to access slots of the object after the C code frees the object (it cannot be tracked automatically).
-
-When object is created by lisp code (using @fun{make-instance}), it is owned by lisp code unless explicitly disowned by @fun{disown-boxed-ref}. Disowning should be done when the object is passed to some function that becomes the owner of the reference.
-
-When object is returned from a function, it depends on a function whether lisp code is the owner of GBoxed object. Return values and arguments of foreign functions are marked with CFFI foreign-type called @class{g-boxed-ref-type} that specifies (by the value of its @code{owner} slot) which code owns the reference."))
-
-(defvar *g-boxed-gc-lock* (make-recursive-lock "g-boxed-gc-lock"))
-(defvar *known-boxed-refs* (tg:make-weak-hash-table :test 'equal :weakness :value))
-(defvar *boxed-ref-count* (make-hash-table :test 'equal))
-(defvar *boxed-ref-owner* (make-hash-table :test 'equal))
-
-(defun boxed-ref-free-function (name)
-  (or (get name 'free-function)
-      (error "g-boxed-ref class ~A has no free-function" name)))
-
-(defun disown-boxed-ref (object)
-  "Specify that the Lisp code no longer owns the reference to the @code{object}. Otherwise garbage collector would collect the @code{object} and corresponding C structure would be freed, causing dangling pointer (if C code does not free the structure) of double free (if C code frees the structure).
-
-@arg[object]{an instance of @class{g-boxed-ref}}"
-  (setf (gethash (pointer-address (pointer object)) *boxed-ref-owner*) :foreign))
-
-(defun dispose-boxed-ref (type pointer)
-  (debugf "disposing g-boxed-ref ~A~%" pointer)
-  
-  (unless (gethash (pointer-address pointer) *boxed-ref-count*)
-    (error "g-boxed-ref ~A is already disposed from lisp-side" pointer))
-  (with-recursive-lock-held (*g-boxed-gc-lock*)
-    (let ((object (gethash (pointer-address pointer) *known-boxed-refs*)))
-      (when object
-        (debugf "Removing finalization from ~A for pointer ~A~%" object pointer)
-        (tg:cancel-finalization object)))
-    (when (eq :lisp (gethash (pointer-address pointer) *boxed-ref-owner*))
-      (funcall (boxed-ref-free-function type) pointer))
-    (remhash (pointer-address pointer) *known-boxed-refs*)
-    (remhash (pointer-address pointer) *boxed-ref-count*)
-    (remhash (pointer-address pointer) *boxed-ref-owner*)
-    (debugf "Disposed of g-boxed-ref ~A (object ~A)~%"
-            pointer
-            (gethash (pointer-address pointer) *known-boxed-refs*))))
-
-(defmethod initialize-instance :after ((object g-boxed-ref) &key)
-  (with-recursive-lock-held (*g-boxed-gc-lock*)
-    (let ((address (pointer-address (pointer object))))
-      (let ((object (gethash address *known-boxed-refs*)))
-        (when object
-          (tg:cancel-finalization object)))
-      (setf (gethash address *known-boxed-refs*) object)
-      (setf (gethash address *boxed-ref-count*) 1)
-      (setf (gethash address *boxed-ref-owner*)
-            (gethash address *boxed-ref-owner* :foreign)))
-    (debugf "setting g-boxed-ref-count of ~A (for ptr ~A) to 1~%" object (pointer object))
-    (let ((p (pointer object))
-          (type (type-of object))
-          (s (format nil "~A" object)))
-      (tg:finalize object (lambda ()                          
-                            (handler-case
-                                (dispose-boxed-ref type p)
-                              (error (e) (format t "Error ~A for ~A~%" e s))))))))
-
-(defmethod release ((object g-boxed-ref))
-  (debugf "releasing g-boxed-ref ~A~%" (pointer object))
-  (unless (gethash (pointer-address (pointer object)) *boxed-ref-count*)
-    (error "g-boxed-ref ~A is already disposed from lisp-side" (pointer object)))
-  (decf (gethash (pointer-address (pointer object)) *boxed-ref-count*))
-  (when (zerop (gethash (pointer-address (pointer object)) *boxed-ref-count*))
-    (dispose-boxed-ref (type-of object) (pointer object))))
-
-(define-foreign-type g-boxed-ref-type ()
-  ((class-name :reader g-boxed-ref-class-name :initarg :class-name)
-   (owner :reader g-boxed-ref-owner :initarg :owner :initform nil))
-  (:actual-type :pointer))
-
-(define-parse-method g-boxed-ref (class-name &key (owner :foreign))
-  (unless (get class-name 'is-g-boxed-ref)
-    (error "~A is not a subtype of G-BOXED-REF (~A: ~S)" class-name class-name (symbol-plist class-name)))
-  (make-instance 'g-boxed-ref-type :class-name class-name :owner owner))
-
-(defmethod translate-to-foreign (value (type g-boxed-ref-type))
-  (if value
-      (pointer value)
-      (null-pointer)))
-
-(defun convert-g-boxed-ref-from-pointer (pointer name type)
-  (unless (null-pointer-p pointer)
-    (with-recursive-lock-held (*g-boxed-gc-lock*)
-      (or (let ((object (gethash (pointer-address pointer) *known-boxed-refs*)))
-            (when object (debugf "Boxed-ref for ~A is found (~A)~%" pointer object))
-            (when object (incf (gethash (pointer-address pointer) *boxed-ref-count*)))
-            object)
-          (let ((object (make-instance name :pointer pointer)))
-            (setf (gethash (pointer-address pointer) *boxed-ref-owner*) (g-boxed-ref-owner type))
-            (debugf "Boxed-ref for ~A is created (~A) with owner ~A~%" pointer object
-                    (gethash (pointer-address pointer) *boxed-ref-owner*))
-            object)))))
-
-(defmethod translate-from-foreign (value (type g-boxed-ref-type))
-  (let ((owner (or (gethash (pointer-address value) *boxed-ref-owner*) (g-boxed-ref-owner type)))) ;;This is needed to prevent changing ownership of already created
-    (prog1
-        (convert-g-boxed-ref-from-pointer value (g-boxed-ref-class-name type) type)
-      (setf (gethash (pointer-address value) *boxed-ref-owner*) owner))))
-
-(defun g-boxed-ref-slot->methods (class slot)
-  (destructuring-bind (slot-name &key reader writer type (accessor slot-name)) slot
-    `(progn ,@(when reader
-                    (list `(defmethod ,accessor ((object ,class))
-                             ,(if (stringp reader)
-                                  `(foreign-funcall ,reader :pointer (pointer object) ,type)
-                                  `(,reader object)))))
-            ,@(when writer
-                    (list `(defmethod (setf ,accessor) (new-value (object ,class))
-                             ,(if (stringp writer)
-                                  `(foreign-funcall ,writer :pointer (pointer object) ,type new-value)
-                                  `(,writer new-value object))))))))
-
-(defmacro define-g-boxed-ref (gobject-name name &rest properties)
-  "Defines a class corresponding to GBoxed type that is passed by reference (e.g., GtkTextIter). Class is made a subclass of @code{g-boxed-ref}.
-
-Example:
-@begin{pre}
-\(defun tree-iter-alloc () (glib:g-malloc (foreign-type-size 'tree-iter)))
-\(defun tree-iter-free (v) (glib:g-free v))
-
-\(define-g-boxed-ref \"GtkTreeIter\" tree-iter
-  (:slots (stamp :reader tree-iter-get-stamp :writer tree-iter-set-stamp :accessor tree-iter-stamp)
-          (user-data :reader tree-iter-get-user-data :writer tree-iter-set-user-data :accessor tree-iter-user-data))
-  (:alloc-function tree-iter-alloc)
-  (:free-function tree-iter-free))
-@end{pre}
-@arg[gobject-name]{a string denoting the GObject type}
-@arg[name]{a symbol denoting the class name for generated class}
-@arg[properties]{p-list of options.
-Each option is a list @code{(name value)} where @code{name} is name of an option and @code{value} is its value.
-Following options are used:
-@begin{itemize}
-@item{@code{:free-function} (mandatory). Designator for a function that frees the allocated object. Accepts a single argument - pointer.}
-@item{@code{:alloc-function} (mandator). Designator for a function that accepts zero arguments and returns the C pointer to newly allocated object.}
-@item{@code{:slots} (optional). Slots specifications for GBoxed.
-Each slot is specified as a list @code{(slot-name &key reader writer type (accessor slot-name))}.
-@begin{itemize}
-@item{@code{slot-name} is a symbol - the name of a slot}
-@item{@code{type} is a CFFI type of a slot}
-@item{@code{reader} is a @code{NIL} or a string or a function designator.
-
-If it is a @code{NIL} then the slot is not readable.
-
-If it is a string then it names the C function that accepts the pointer to C structure and returns the value of a slot (of specified CFFI type). 
-
-If it is a function designator then it specifies a function that accepts the Lisp object and returns its slot value.}
-@item{@code{writer} is a @code{NIL} or string or a function designator.
-
-If it is a @code{NIL} then the slot is not writable.
-
-If it is a string then it names the C function that accepts the pointer to C structure and a value (of specified CFFI type) and assigns it to the slot of a structure. and returns the value of a slot (of specified CFFI type).
-
-If it is a function designator then it specifies a function that accepts the new slot value and a Lisp object and assigns it to the slot.}
-@item{@code{accessor} is a symbol that names accessor function for this slot. By default it equals to @code{slot-name}.}
-@end{itemize}
-}
-@end{itemize}
-}"
-  (let ((free-fn (second (find :free-function properties :key 'first)))
-        (alloc-fn (second (find :alloc-function properties :key 'first)))
-        (slots (rest (find :slots properties :key 'first))))
-    (unless (and free-fn alloc-fn) (error "All of :free-function, :alloc-function must be specified"))
-    `(progn (defclass ,name (g-boxed-ref) ())
-            (defmethod initialize-instance :before ((object ,name) &key pointer)
-              (unless (or pointer (slot-boundp object 'pointer))
-                (setf (pointer object) (,alloc-fn)
-                      (gethash (pointer-address (pointer object)) *boxed-ref-owner*) :lisp)))
-            (setf (get ',name 'free-function) ',free-fn)
-            (eval-when (:compile-toplevel :load-toplevel :execute)
-              (setf (get ',name 'is-g-boxed-ref) t))
-            ,@(mapcar (lambda (slot)
-                        (g-boxed-ref-slot->methods name slot))
-                      slots)
-            (register-boxed-type ,gobject-name ',name))))
-
-(define-foreign-type fixed-array ()
-  ((element-type :reader fixed-array-element-type :initarg :element-type :initform (error "Element type must be specified"))
-   (array-size :reader fixed-array-array-size :initarg :array-size :initform (error "Array size must be specified")))
-  (:actual-type :pointer)
-  (:documentation
-"CFFI foreign type for an array of a fixed length. Slot @code{element-type}@see-slot{fixed-array-element-type} specifies the type of elements and slot @code{array-size}@see-slot{fixed-array-array-size} specifies the size of array (in elements)."))
-
-(define-parse-method fixed-array (element-type array-size)
-  (make-instance 'fixed-array :element-type element-type :array-size array-size))
-
-(defmethod translate-from-foreign (ptr (type fixed-array))
-  (when (not (null-pointer-p ptr))
-    (let ((result (make-array (fixed-array-array-size type)))
-          (el-type (fixed-array-element-type type)))
-      (loop
-         for i from 0 below (fixed-array-array-size type)
-         do (setf (aref result i) (mem-aref ptr el-type i)))
-      result)))
-
-(defvar *registered-boxed-types* (make-hash-table :test 'equal))
-(defvar *registered-boxed-names* (make-hash-table))
-(defun register-boxed-type (name type)
-  (setf (gethash name *registered-boxed-types*) type
-        (gethash type *registered-boxed-names*) name))
-(defun get-registered-boxed-type (name)
-  (gethash name *registered-boxed-types*))
-
-(defun boxed-type-gname (type)
-  (gethash type *registered-boxed-names*))
-
-(defun set-gvalue-boxed (gvalue value)
-  (if value
-      (progn
-        (cond
-          ((typep value 'g-boxed-ref)
-           (g-value-set-boxed gvalue (pointer value)))
-          (t (g-value-take-boxed gvalue (g-boxed->cstruct value :alloc-type :boxed)))))
-      (g-value-set-boxed gvalue (null-pointer))))
-
-(defun parse-g-value-boxed (gvalue)
-  (let* ((g-type (g-value-type gvalue))
-         (type-name (g-type-name g-type))
-         (boxed-type (get-registered-boxed-type type-name)))
-    (unless boxed-type
-      (warn "Type ~A is a not registered GBoxed~%" type-name)
-      (return-from parse-g-value-boxed nil))
-    (unless (null-pointer-p (g-value-get-boxed gvalue))
-      (cond
-        ((subtypep boxed-type 'g-boxed-ref) (convert-g-boxed-ref-from-pointer (g-value-get-boxed gvalue) boxed-type (make-instance 'g-boxed-ref-type :class-name boxed-type :owner :foreign)))
-        (t (parse-g-boxed (g-value-get-boxed gvalue) boxed-type))))))
-
-(defmethod parse-g-value-for-type (gvalue-ptr (type-numeric (eql +g-type-boxed+)) parse-kind)
-  (declare (ignore parse-kind))
-  (if (g-type= (g-value-type gvalue-ptr) (g-strv-get-type))
-      (convert-from-foreign (g-value-get-boxed gvalue-ptr) '(glib:gstrv :free-from-foreign nil))
-      (parse-g-value-boxed gvalue-ptr)))
-
-(defmethod set-gvalue-for-type (gvalue-ptr (type-numeric (eql +g-type-boxed+)) value)
-  (format t "Converting ~A of GBoxed type ~A~%" value (g-type-string (g-value-type gvalue-ptr)))
-  (if (g-type= (g-value-type gvalue-ptr) (g-strv-get-type))
-      (g-value-set-boxed gvalue-ptr (convert-to-foreign value '(glib:gstrv :free-from-foreign nil)))
-      (set-gvalue-boxed gvalue-ptr value)))
-