+(defmethod from-alien-form (location (class proxy-class) &rest args)
+ (declare (ignore args))
+ `(ensure-proxy-instance ',(class-name class) ,location))
+
+(defmethod from-alien-function ((class proxy-class) &rest args)
+ (declare (ignore args))
+ #'(lambda (location)
+ (ensure-proxy-instance class location)))
+
+(defmethod to-alien-form (instance (class proxy-class) &rest args)
+ (declare (ignore class args))
+ `(foreign-location ,instance))
+
+(defmethod to-alien-function ((class proxy-class) &rest args)
+ (declare (ignore class args))
+ #'foreign-location)
+
+(defmethod copy-from-alien-form (location (class proxy-class) &rest args)
+ (declare (ignore args))
+ (let ((class-name (class-name class)))
+ `(ensure-proxy-instance ',class-name
+ (reference-foreign ',class-name ,location))))
+
+(defmethod copy-from-alien-function ((class proxy-class) &rest args)
+ (declare (ignore args))
+ #'(lambda (location)
+ (ensure-proxy-instance class (reference-foreign class location))))
+
+(defmethod copy-to-alien-form (instance (class proxy-class) &rest args)
+ (declare (ignore args))
+ `(reference-foreign ',(class-name class) (foreign-location ,instance)))
+
+(defmethod copy-to-alien-function ((class proxy-class) &rest args)
+ (declare (ignore args))
+ #'(lambda (instance)
+ (reference-foreign class (foreign-location instance))))
+
+(defmethod writer-function ((class proxy-class) &rest args)
+ (declare (ignore args))
+ #'(lambda (instance location &optional (offset 0))
+ (assert (null-pointer-p (sap-ref-sap location offset)))
+ (setf
+ (sap-ref-sap location offset)
+ (reference-foreign class (foreign-location instance)))))
+
+(defmethod reader-function ((class proxy-class) &rest args)
+ (declare (ignore args))
+ #'(lambda (location &optional (offset 0) weak-p)
+ (declare (ignore weak-p))
+ (let ((instance (sap-ref-sap location offset)))
+ (unless (null-pointer-p instance)
+ (ensure-proxy-instance class (reference-foreign class instance))))))
+
+(defmethod destroy-function ((class proxy-class) &rest args)
+ (declare (ignore args))
+ #'(lambda (location &optional (offset 0))
+ (unreference-foreign class (sap-ref-sap location offset))))
+
+(defmethod unbound-value ((class proxy-class) &rest args)
+ (declare (ignore args))
+ (values t nil))
+
+(defun ensure-proxy-instance (class location &rest initargs)
+ "Returns a proxy object representing the foreign object at the give
+location. If an existing object is not found in the cache
+MAKE-PROXY-INSTANCE is called to create one."
+ (unless (null-pointer-p location)
+ (or
+ #-debug-ref-counting(find-cached-instance location)
+ #+debug-ref-counting
+ (let ((instance (find-cached-instance location)))
+ (when instance
+ (format t "Object found in cache: ~A~%" instance)
+ instance))
+ (let ((instance (apply #'make-proxy-instance class location initargs)))
+ (cache-instance instance)
+ instance))))
+
+(defgeneric make-proxy-instance (class location &key weak)
+ (:documentation "Creates a new proxy object representing the foreign
+object at the give location. If WEAK is non NIL the foreign memory
+will not be released when the proxy is garbage collected."))
+
+(defmethod make-proxy-instance ((class symbol) location &rest initargs)
+ (apply #'make-proxy-instance (find-class class) location initargs))
+
+(defmethod make-proxy-instance ((class proxy-class) location &key weak)
+ (let ((instance
+ (or
+ (find-invalidated-instance class)
+ (allocate-instance class))))
+ (setf (slot-value instance 'location) location)
+ (unless weak
+ (finalize instance (instance-finalizer instance)))
+ instance))