summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Benkard <code@mail.matthias.benkard.de>2007-09-14 20:21:46 +0200
committerMatthias Benkard <code@mail.matthias.benkard.de>2007-09-14 20:21:46 +0200
commit25cc1a489ff21bedae0a9ebfc9b462113ccc56c7 (patch)
tree6baf0022d6d5ffa0e193dd9be165f1ffc0a6a14d
parentb6418f77118e823781edf80b461d14adf1fd8d41 (diff)
Introduce PRIMITIVE-INVOKE, a lower-level INVOKE-BY-NAME alternative written in Lisp only.
darcs-hash:cc01d5054194e3be05efa9fc002da30e04d7068e
-rw-r--r--Lisp/data-types.lisp16
-rw-r--r--Lisp/libobjcl.lisp2
-rw-r--r--Lisp/method-invocation.lisp34
3 files changed, 43 insertions, 9 deletions
diff --git a/Lisp/data-types.lisp b/Lisp/data-types.lisp
index b22057f..35acb2f 100644
--- a/Lisp/data-types.lisp
+++ b/Lisp/data-types.lisp
@@ -172,10 +172,10 @@ an __exception__, you can simply send it the `self' message.
(defmethod print-object ((object id) stream)
(print-unreadable-object (object stream)
(format stream "~A `~A' {~X}"
- (objcl-class-name (invoke-by-name object "class"))
- (invoke-by-name (invoke-by-name object "description")
- "UTF8String")
- (invoke-by-name object "hash"))))
+ (objcl-class-name (primitive-invoke object "class" :id))
+ (primitive-invoke (primitive-invoke object "description" :id)
+ "UTF8String" :string)
+ (primitive-invoke object "hash" :unsigned-int))))
(defmethod print-object ((class objc-class) stream)
@@ -183,7 +183,7 @@ an __exception__, you can simply send it the `self' message.
(format stream "~S ~A {~X}"
'objc-class
(objcl-class-name class)
- (invoke-by-name class "hash"))))
+ (primitive-invoke class "hash" :unsigned-int))))
(defmethod print-object ((selector selector) stream)
@@ -197,9 +197,9 @@ an __exception__, you can simply send it the `self' message.
(print-unreadable-object (exception stream)
(format stream "~S ~A {~X}"
'exception
- (invoke-by-name (invoke-by-name exception "name")
- "UTF8String")
- (invoke-by-name exception "hash"))))
+ (primitive-invoke (primitive-invoke exception "name" :id)
+ "UTF8String" :string)
+ (primitive-invoke exception "hash" :unsigned-int))))
;;;; (@* "Convenience types")
diff --git a/Lisp/libobjcl.lisp b/Lisp/libobjcl.lisp
index bf80c30..d5d7379 100644
--- a/Lisp/libobjcl.lisp
+++ b/Lisp/libobjcl.lisp
@@ -290,7 +290,7 @@ by which __invoke__ converts its arguments into a *message name*.
'(satisfies cffi:pointerp)))
-(declaim (ftype (function ((or selector string list)) selector)
+(declaim (ftype (function ((or selector string symbol list)) selector)
selector))
(defun selector (designator)
"Convert an object into a selector.
diff --git a/Lisp/method-invocation.lisp b/Lisp/method-invocation.lisp
index 99ebf7b..5da06b8 100644
--- a/Lisp/method-invocation.lisp
+++ b/Lisp/method-invocation.lisp
@@ -147,6 +147,40 @@ Returns: *result* --- the return value of the method invocation.
(dealloc-objc-arglist objc-arglist)))))
+(defmacro primitive-invoke (receiver method-name return-type &rest args)
+ (let ((real-return-type (if (member return-type '(:id :class :exception))
+ :pointer
+ return-type))
+ (real-receiver (gensym))
+ (real-selector (gensym))
+ (selector (selector method-name)))
+ `(progn
+ (let ((,real-receiver ,receiver)
+ (,real-selector (selector ,method-name)))
+ (check-type ,real-receiver (or id objc-class exception)
+ "an Objective C instance (ID, OBJC-CLASS or EXCEPTION)")
+ (let ((method (get-method-implementation ,real-receiver ,real-selector))
+ (objc-arglist (arglist->objc-arglist (list ,@args))))
+ (unwind-protect
+ (let ((return-value
+ (apply-macro 'foreign-funcall-pointer method
+ ()
+ (append (list :pointer (pointer-to ,real-receiver))
+ (list :pointer (pointer-to ,real-selector))
+ objc-arglist
+ (list ,real-return-type)))))
+ ,(if (member return-type '(:id :class :exception))
+ `(let (,@(when (constructor-name-p (selector-name selector))
+ `((*skip-retaining* t))))
+ (make-instance ',(case return-type
+ ((:id) 'id)
+ ((:class) 'objc-class)
+ ((:exception) 'exception))
+ :pointer return-value))
+ `return-value))
+ (dealloc-objc-arglist objc-arglist)))))))
+
+
;;; (@* "Helper functions")
(defun arglist->objc-arglist (arglist)
(arglist-intersperse-types (mapcar #'lisp->obj-data arglist)))