+
+(defun boxed-related-symbols (name)
+ (let ((info (get-g-boxed-foreign-info name)))
+ (etypecase info
+ (g-boxed-cstruct-wrapper-info
+ (append (list name
+ (intern (format nil "MAKE-~A" (symbol-name name)))
+ (intern (format nil "COPY-~A" (symbol-name name))))
+ (iter (for slot in (cstruct-description-slots (g-boxed-cstruct-wrapper-info-cstruct-description info)))
+ (for slot-name = (cstruct-slot-description-name slot))
+ (collect (intern (format nil "~A-~A" (symbol-name name) (symbol-name slot-name)))))))
+ (g-boxed-opaque-wrapper-info
+ (list name))
+ (g-boxed-variant-cstruct-info
+ (append (list name)
+ (iter (for var-struct in (all-structures (g-boxed-variant-cstruct-info-root info)))
+ (for s-name = (var-structure-name var-struct))
+ (for cstruct-description = (var-structure-resulting-cstruct-description var-struct))
+ (appending (append (list s-name)
+ (list (intern (format nil "MAKE-~A" (symbol-name s-name)))
+ (intern (format nil "COPY-~A" (symbol-name s-name))))
+ (iter (for slot in (cstruct-description-slots cstruct-description))
+ (for slot-name = (cstruct-slot-description-name slot))
+ (collect (intern (format nil "~A-~A" (symbol-name s-name)
+ (symbol-name slot-name)))))))))))))
+
+(defmacro define-boxed-opaque-accessor (boxed-name accessor-name &key type reader writer)
+ (let ((var (gensym))
+ (n-var (gensym)))
+ `(progn ,@(when reader
+ (list (etypecase reader
+ (symbol `(defun ,accessor-name (,var)
+ (funcall ,reader ,var)))
+ (string `(defcfun (,accessor-name ,reader) ,type
+ (,var (g-boxed-foreign ,boxed-name)))))))
+ ,@(when writer
+ (list (etypecase reader
+ (symbol `(defun (setf ,accessor-name) (,n-var ,var)
+ (funcall ,reader ,n-var ,var)))
+ (string `(defun (setf ,accessor-name) (,n-var ,var)
+ (foreign-funcall ,writer (g-boxed-foreign ,boxed-name) ,var ,type ,n-var :void)))))))))
+
+(defun copy-boxed-slots-to-foreign (structure native-ptr &optional (type (and structure (type-of structure))))
+ (when structure
+ (copy-slots-to-native
+ structure
+ native-ptr
+ (g-boxed-cstruct-wrapper-info-cstruct-description (get-g-boxed-foreign-info type)))))
+
+(define-compiler-macro copy-boxed-slots-to-foreign (&whole whole structure native-ptr &optional type)
+ (if (and type
+ (constantp type))
+ (let* ((type-r (eval type))
+ (f-i (get-g-boxed-foreign-info type-r)))
+ (unless f-i
+ (warn "Unknown foreign GBoxed type ~S" type-r)
+ (return-from copy-boxed-slots-to-foreign whole))
+ (unless (typep f-i 'g-boxed-cstruct-wrapper-info)
+ (warn "Foreign GBoxed type ~S is not a C structure wrapper" type-r)
+ (return-from copy-boxed-slots-to-foreign whole))
+ `(when ,structure
+ (copy-slots-to-native
+ ,structure
+ ,native-ptr
+ (load-time-value (g-boxed-cstruct-wrapper-info-cstruct-description (get-g-boxed-foreign-info ',type-r))))))
+ whole))
+
+(defmacro with-foreign-boxed-array ((n-var array-var type values-seq) &body body)
+ (let ((values-seq-1 (gensym "VALUES-SEQ-"))
+ (cstruct (generated-cstruct-name type))
+ (x (gensym "X-"))
+ (i (gensym "I-")))
+ `(let* ((,values-seq-1 ,values-seq)
+ (,n-var (length ,values-seq-1)))
+ (with-foreign-object (,array-var ',cstruct ,n-var)
+ (let ((,i 0))
+ (map nil (lambda (,x)
+ (copy-boxed-slots-to-foreign
+ ,x
+ (inc-pointer ,array-var (* ,i (foreign-type-size ',cstruct)))
+ ',type)
+ (incf ,i))
+ ,values-seq-1))
+ ,@body))))