Changeset 233
- Timestamp:
- Jan 7, 2004, 7:42:22 AM (21 years ago)
- File:
-
- 1 edited
-
trunk/ccl/examples/objc-clos.lisp (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/examples/objc-clos.lisp
r231 r233 14 14 ;;; The LLGPL is also available online at 15 15 ;;; 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 16 27 17 28 (in-package "CCL") … … 23 34 (use-interface-dir :gnustep)) 24 35 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 25 44 (defpackage "NS" 26 45 (:use)) 27 46 28 29 ;;; Force all symbols interned in the NS package to be external30 ;;; symbols.31 47 (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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32 69 33 70 (defconstant objc-type-flags (byte 3 20)) … … 105 142 :class-of #'%objc-domain-class-of 106 143 :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 109 148 :slots-vector #'%objc-domain-slots-vector) 110 149 111 150 151 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 152 ;;;; OBJC Objects, Classes and Metaclasses ;;;; 153 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 112 154 113 155 (defclass objc:objc-object (foreign-standard-object) … … 140 182 (defmethod print-object ((c objc:objc-class) stream) 141 183 (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)))) 143 189 144 190 (defmethod print-object ((c objc:objc-metaclass) stream) 145 191 (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)))) 147 196 148 197 (defmethod print-object ((o objc:objc-object) stream) … … 150 199 (format stream "~a (#x~x)" (nsobject-description o) (%ptr-to-int o)))) 151 200 152 (defmethod slot-value-using-class ((class objc:objc-class-object)153 instance154 (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 instance159 (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 (new164 (class objc:objc-class-object)165 instance166 (slotd standard-effective-slot-definition))167 (%set-std-slot-vector-value (%objc-domain-slots-vector instance) slotd new))168 201 169 202 170 203 (defun initialize-objc-class-slots (class class-name wrapper &optional foreign) 171 204 ; (format t "~&initialize-objc-class-slots ~s (#x~x)" class-name (%ptr-to-int class)) 172 ; (force-output)205 ; (force-output) 173 206 (let* ((super (pref class :objc_class.super_class)) 174 207 (super-id (unless (%null-ptr-p super) (objc-class-id super))) … … 198 231 ))) 199 232 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) 202 236 ; (force-output) 203 237 (let* ((super (pref class :objc_class.super_class)) … … 230 264 ))) 231 265 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.
