support for setting gvalue to values of g-boxed-class
[cl-gtk2.git] / glib / gobject.foreign-gboxed.lisp
index 7f83a09..abae705 100644 (file)
     (real-parse-g-boxed pointer object)
     object))
 
-(defun g-boxed->cstruct (object)
-  (let ((pointer (foreign-alloc (type-of 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))
 
     (with-recursive-lock-held (*g-boxed-gc-lock*)
      (or (aprog1 (gethash (pointer-address pointer) *known-boxed-refs*)
            (when it (debugf "Boxed-ref for ~A is found (~A)~%" pointer it))
+           (when it (incf (gethash (pointer-address pointer) *boxed-ref-count*)))
            it)
          (aprog1 (make-instance name :pointer pointer)
            (setf (gethash (pointer-address pointer) *boxed-ref-owner*) (g-boxed-ref-owner type))
       (setf (gethash (pointer-address value) *boxed-ref-owner*) owner))))
 
 (defun g-boxed-ref-slot->methods (class slot)
-  (bind (((slot-name &key reader writer type) slot))
+  (bind (((slot-name &key reader writer type (accessor slot-name)) slot))
     `(progn ,@(when reader
-                    (list `(defmethod ,slot-name ((object ,class))
+                    (list `(defmethod ,accessor ((object ,class))
                              ,(if (stringp reader)
                                   `(foreign-funcall ,reader :pointer (pointer object) ,type)
                                   `(,reader object)))))
             ,@(when writer
-                    (list `(defmethod (setf ,slot-name) (new-value (object ,class))
+                    (list `(defmethod (setf ,accessor) (new-value (object ,class))
                              ,(if (stringp writer)
                                   `(foreign-funcall ,writer :pointer (pointer object) ,type new-value)
                                   `(,writer new-value object))))))))
       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))
+  (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
-        (unless (typep value 'g-boxed-ref) (error "Can only set g-boxed-ref!"))
-        (g-value-set-boxed gvalue (pointer value)))
+        (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-gvalue-boxed (gvalue)