Changeset 233


Ignore:
Timestamp:
Jan 7, 2004, 7:42:22 AM (21 years ago)
Author:
beer
Message:

Added support for foreign slot definitions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/examples/objc-clos.lisp

    r231 r233  
    1414;;;   The LLGPL is also available online at
    1515;;;   http://opensource.franz.com/preamble.html
     16;;;
     17;;; TO DO
     18;;;  - Need to add getter and setter functions for more foriegn slot types
     19;;;  - OBJC-FOREIGN-ARG-TYPE in BRIDGE.LISP needs to handle BITFIELDs,
     20;;;    ARRAYs and UNIONs
     21;;;  - Need to get enough of the instance initialization and XXX
     22;;;    protocols working so that foreign slot objects actually show up
     23;;;    where they're supposed to
     24;;;  - Implement slot access for OBJC-CLASS lisp slots
     25
     26;;; Package and module stuff
    1627
    1728(in-package "CCL")
     
    2334  (use-interface-dir :gnustep))
    2435
     36;;; We need OBJC-FOREIGN-ARG-TYPE from the bridge to process ivar types
     37
     38(require "BRIDGE")
     39
     40;;; All class names and instance variable names are interned in the NS package
     41;;; Force all symbols interned in the NS package to be external
     42;;; symbols.
     43
    2544(defpackage "NS"
    2645  (:use))
    2746
    28 
    29 ;;; Force all symbols interned in the NS package to be external
    30 ;;; symbols.
    3147(package-force-export "NS")
     48
     49
     50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     51;;;;                                 Testing                                ;;;;
     52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     53
     54;;; Until foreign slot definition objects automatically show up where they're
     55;;; supposed to, this function manually sets them up for a given ObjC class
     56;;; (and its superclasses)
     57
     58(defun init-objc-class-slot-definitions (c)
     59  (unless (eql c (%null-ptr))
     60    (init-objc-class-slot-definitions (pref c :objc_class.super_class))
     61    (setf (slot-value c 'direct-slots) (%compute-foreign-direct-slots c))
     62    (setf (slot-value c 'slots) (compute-slots c))
     63    (values)))
     64
     65
     66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     67;;;;                     OBJC Foreign Object Domain                         ;;;;
     68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    3269
    3370(defconstant objc-type-flags (byte 3 20))
     
    105142                                :class-of #'%objc-domain-class-of
    106143                                :classp #'%objc-domain-classp
    107                                 :instance-class-wrapper #'%objc-domain-instance-class-wrapper
    108                                 :class-own-wrapper #'%objc-domain-class-own-wrapper
     144                                :instance-class-wrapper
     145                                #'%objc-domain-instance-class-wrapper
     146                                :class-own-wrapper
     147                                #'%objc-domain-class-own-wrapper
    109148                                :slots-vector #'%objc-domain-slots-vector)
    110149
    111150
     151;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     152;;;;                  OBJC Objects, Classes and Metaclasses                 ;;;;
     153;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    112154
    113155(defclass objc:objc-object (foreign-standard-object)
     
    140182(defmethod print-object ((c objc:objc-class) stream)
    141183  (print-unreadable-object (c stream)
    142     (format stream "~s ~:[~;[MetaClass] ~]~s (#x~x)" 'objc:objc-class (objc-metaclass-p c) (class-name c) (%ptr-to-int c))))
     184    (format stream "~s ~:[~;[MetaClass] ~]~s (#x~x)"
     185            'objc:objc-class
     186            (objc-metaclass-p c)
     187            (class-name c)
     188            (%ptr-to-int c))))
    143189
    144190(defmethod print-object ((c objc:objc-metaclass) stream)
    145191  (print-unreadable-object (c stream)
    146     (format stream "~s ~s (#x~x)" 'objc:objc-metaclass (class-name c) (%ptr-to-int c))))
     192    (format stream "~s ~s (#x~x)"
     193            'objc:objc-metaclass
     194            (class-name c)
     195            (%ptr-to-int c))))
    147196
    148197(defmethod print-object ((o objc:objc-object) stream)
     
    150199    (format stream "~a (#x~x)" (nsobject-description o) (%ptr-to-int o))))
    151200
    152 (defmethod slot-value-using-class ((class objc:objc-class-object)
    153                                    instance
    154                                    (slotd standard-effective-slot-definition))
    155   (%std-slot-vector-value (%objc-domain-slots-vector instance) slotd))
    156 
    157 (defmethod slot-boundp-using-class ((class objc:objc-class-object)
    158                                     instance
    159                                     (slotd standard-effective-slot-definition))
    160   (%std-slot-vector-boundp (%objc-domain-slots-vector instance) slotd))
    161 
    162 (defmethod (setf slot-value-using-class)
    163     (new
    164      (class objc:objc-class-object)
    165      instance
    166      (slotd standard-effective-slot-definition))
    167   (%set-std-slot-vector-value (%objc-domain-slots-vector instance) slotd new))
    168201
    169202
    170203(defun initialize-objc-class-slots (class class-name wrapper &optional foreign)
    171204;  (format t "~&initialize-objc-class-slots ~s (#x~x)" class-name (%ptr-to-int class)) 
    172  ; (force-output)
     205; (force-output)
    173206  (let* ((super (pref class :objc_class.super_class))
    174207         (super-id (unless (%null-ptr-p super) (objc-class-id super)))
     
    198231             )))
    199232
    200 (defun initialize-objc-metaclass-slots (class class-name wrapper &optional foreign peer)
    201 ;  (format t "~&initialize-objc-metaclass-slots ~s (#x~x)" class-name (%ptr-to-int class))
     233(defun initialize-objc-metaclass-slots (class class-name wrapper
     234                                        &optional foreign peer)
     235;  (format t "~&initialize-objc-metaclass-slots ~s" class-name)
    202236;  (force-output)
    203237  (let* ((super (pref class :objc_class.super_class))
     
    230264             )))
    231265
     266
     267;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     268;;;;                        OBJC-CLASS Slot Protocol                        ;;;;
     269;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     270
     271;;; Accessing Lisp slots
     272
     273(defmethod slot-boundp-using-class ((class objc:objc-class-object)
     274                                    instance
     275                                    (slotd standard-effective-slot-definition))
     276  (%std-slot-vector-boundp (%objc-domain-slots-vector instance) slotd))
     277
     278(defmethod slot-value-using-class ((class objc:objc-class-object)
     279                                   instance
     280                                   (slotd standard-effective-slot-definition))
     281  (%std-slot-vector-value (%objc-domain-slots-vector instance) slotd))
     282
     283(defmethod (setf slot-value-using-class)
     284    (new
     285     (class objc:objc-class-object)
     286     instance
     287     (slotd standard-effective-slot-definition))
     288  (%set-std-slot-vector-value (%objc-domain-slots-vector instance) slotd new))
     289
     290
     291;;; Metaclasses for foreign slots
     292
     293(defclass foreign-direct-slot-definition (direct-slot-definition)
     294  ((offset :initarg :offset :reader foreign-slot-definition-offset)))
     295
     296(defclass foreign-effective-slot-definition (effective-slot-definition)
     297  ((getter :type function :accessor foreign-slot-definition-getter)
     298   (setter :type function :accessor foreign-slot-definition-setter)))
     299
     300
     301;;; Use the foreign slot metaclasses if the slot :ALLOCATION is :FOREIGN
     302
     303(defmethod direct-slot-definition-class ((class objc:objc-class-object)
     304                                         &rest initargs)
     305  (if (eq  (getf initargs :allocation) :foreign)
     306      (find-class 'foreign-direct-slot-definition)
     307    (find-class 'standard-direct-slot-definition)))
     308
     309(defmethod effective-slot-definition-class ((class objc:objc-class-object)
     310                                            &rest initargs)
     311  (if (eq (getf initargs :allocation) :foreign)
     312      (find-class 'foreign-effective-slot-definition)
     313    (find-class 'standard-effective-slot-definition)))
     314
     315
     316;;; Create FOREIGN-DIRECT-SLOT-DEFINITIONs for each foreign instance variable
     317;;; in the OBJC-CLASS C
     318
     319(defun %compute-foreign-direct-slots (c)
     320  (when (objc-object-p c)
     321    (with-macptrs ((ivars (pref c :objc_class.ivars)))
     322      (unless (%null-ptr-p ivars)
     323        (loop with ns-package = (find-package "NS")
     324              with n = (pref ivars :objc_ivar_list.ivar_count)
     325              for i from 1 to n
     326              for ivar = (pref ivars :objc_ivar_list.ivar_list)
     327                  then (%inc-ptr ivar (record-length :objc_ivar))
     328              for name = (%get-cstring (pref ivar :objc_ivar.ivar_name))
     329              for sym = (compute-lisp-name name ns-package)
     330              when (eql (schar name 0) #\_)
     331                do (unexport sym ns-package)
     332              collect
     333              (make-direct-slot-definition
     334               c
     335               (list
     336                :name sym
     337                :allocation :foreign
     338                :class (find-class 'foreign-effective-slot-definition)
     339                :type (objc-foreign-arg-type
     340                       (%get-cstring (pref ivar :objc_ivar.ivar_type)))
     341                :offset (pref ivar :objc_ivar.ivar_offset))))))))
     342         
     343
     344;;; Return the getter and setter functions for a foreign slot
     345
     346(defun compute-foreign-slot-accessors (eslotd)
     347  (let ((ftype (%slot-definition-type eslotd)))
     348    (case ftype
     349      (:unsigned-byte (values #'%get-unsigned-byte #'%set-byte))
     350      (:signed-byte (values #'%get-signed-byte #'%set-byte))
     351      (:unsigned-word (values #'%get-unsigned-word #'%set-word))
     352      (:signed-word (values #'%get-signed-word #'%set-word))
     353      (:unsigned-fullword (values #'%get-unsigned-long #'%set-long))
     354      (:signed-fullword (values #'%get-signed-long #'%set-long))
     355      (:unsigned-longlong (values #'%%get-unsigned-longlong #'%%set-unsigned-longlong))
     356      (:signed-longlong (values #'%%get-signed-longlong #'%%set-signed-longlong))
     357      (:single-float (values #'%get-single-float #'%set-single-float))
     358      (:double-float (values #'%get-double-float #'%set-double-float))
     359      ((:id :address) (values #'%get-ptr #'%set-ptr))
     360      (t
     361       (cond
     362        ((and (consp ftype) (eq (first ftype) :*))
     363         (values #'%get-ptr #'%set-ptr))
     364        (t (values
     365            #'(lambda (ptr &optional offset)
     366                (declare (ignore ptr offset))
     367                (error "Unhandled foreign slot type: ~S" ftype))
     368            #'(lambda (ptr &optional offset)
     369                (declare (ignore ptr offset))
     370                (error "Unhandled foreign slot type: ~S" ftype)))))))))
     371
     372
     373;;; Augment SLOT-CLASS's COMPUTE-EFFECTIVE-SLOT-DEFINITION with an :AROUND
     374;;; method for OBJC-CLASSes that sets up foreign slot info
     375
     376(defmethod compute-effective-slot-definition :around ((class objc:objc-class-object)
     377                                                      name
     378                                                      direct-slots)
     379  (declare (ignore name))
     380  (let ((first (first direct-slots))
     381        (eslotd (call-next-method)))
     382    (when (typep eslotd 'foreign-effective-slot-definition)
     383      (setf (slot-value eslotd 'location)
     384            (foreign-slot-definition-offset first))
     385      (multiple-value-bind (getter setter) (compute-foreign-slot-accessors eslotd)
     386        (setf (foreign-slot-definition-getter eslotd) getter)
     387        (setf (foreign-slot-definition-setter eslotd) setter)))
     388    eslotd))
     389
     390
     391;;; Determine the location of each slot
     392
     393(defun collect-slots-with-alloc (alloc slotds)
     394  (loop for slotd in slotds
     395        when (eq (%slot-definition-allocation slotd) alloc)
     396         collect slotd))
     397
     398(defmethod compute-slots :around ((class objc:objc-class-object))
     399  (let* ((cpl (%class-precedence-list class))
     400         (slots (call-next-method))
     401         (instance-slots (collect-slots-with-alloc :instance slots))
     402         (class-slots (collect-slots-with-alloc :class slots))
     403         (foreign-slots (collect-slots-with-alloc :foreign slots)))
     404    (setq instance-slots
     405          (sort-effective-instance-slotds instance-slots class cpl))
     406    (loop for islot in instance-slots
     407          for loc = 1 then (1+ loc)
     408          do (setf (%slot-definition-location islot) loc))
     409    (dolist (cslot class-slots)
     410      (setf (%slot-definition-location cslot)
     411            (assoc (%slot-definition-name cslot)
     412                   (%class-get (%slot-definition-class cslot) :class-slots)
     413                   :test #'eq)))
     414     (append instance-slots class-slots foreign-slots)))
     415
     416
     417;;; Accessing foreign slots
     418
     419(defmethod slot-boundp-using-class ((class objc:objc-class-object)
     420                                    instance
     421                                    (slotd foreign-effective-slot-definition))
     422  (declare (ignore class instance slotd))
     423  ;; foreign slots are always bound
     424  t)
     425
     426(defmethod slot-value-using-class ((class objc:objc-class-object)
     427                                   instance
     428                                   (slotd foreign-effective-slot-definition))
     429  (funcall (foreign-slot-definition-getter slotd)
     430           instance
     431           (slot-definition-location slotd)))
     432
     433(defmethod (setf slot-value-using-class) (value
     434                                          (class objc:objc-class-object)
     435                                          instance
     436                                          (slotd foreign-effective-slot-definition))
     437  (funcall (foreign-slot-definition-setter slotd)
     438           instance
     439           (slot-definition-location slotd)
     440           value))
     441
Note: See TracChangeset for help on using the changeset viewer.