X-Git-Url: http://git.kpe.io/?a=blobdiff_plain;f=src%2Ffunctions.lisp;h=1610b2246849e5e386227965f82c9a0f88fc0279;hb=5a7117c2a750662b4ecd36c62c7c073d76f64b4e;hp=7f0939d5afe2dd20fdcf7d7264096483a39e51fb;hpb=ebedde4e67b858b1f65c5eb4dc7bc45978ed1e40;p=uffi.git diff --git a/src/functions.lisp b/src/functions.lisp index 7f0939d..1610b22 100644 --- a/src/functions.lisp +++ b/src/functions.lisp @@ -48,7 +48,8 @@ (let ((name (car arg)) (type (convert-from-uffi-type (cadr arg) :routine))) #+(or cmu sbcl scl) - (list name type :in) + ;(list name type :in) + `(,name ,type ,@(if (= (length arg) 3) (list (third arg)) (values))) #+(or allegro lispworks (and mcl (not openmcl))) (if (and (listp type) (listp (car type))) (append (list name) type) @@ -63,9 +64,114 @@ (list type) type)) +(defun funcallable-lambda-list (args) + (let ((ll nil)) + (dolist (arg args) + (push (car arg) ll)) + (nreverse ll))) + +#| +(defmacro def-funcallable (name args &key returning) + (let ((result-type (convert-from-uffi-type returning :return)) + (function-args (process-function-args args))) + #+lispworks + `(fli:define-foreign-funcallable ,name ,function-args + :result-type ,result-type + :language :ansi-c + :calling-convention :cdecl) + #+(or cmu scl sbcl) + ;; requires the type of the function pointer be declared correctly! + (let* ((ptrsym (gensym)) + (ll (funcallable-lambda-list args))) + `(defun ,name ,(cons ptrsym ll) + (alien::alien-funcall ,ptrsym ,@ll))) + #+openmcl + (multiple-value-bind (params args) (process-function-args args) + (let ((ptrsym (gensym))) + `(defun ,name ,(cons ptrsym params) + (ccl::ff-call ,ptrsym ,@args ,result-type)))) + #+allegro + ;; this is most definitely wrong + (let* ((ptrsym (gensym)) + (ll (funcallable-lambda-list args))) + `(defun ,name ,(cons ptrsym ll) + (system::ff-funcall ,ptrsym ,@ll))) + )) +|# + +(defun convert-lispworks-args (args) + (loop for arg in args + with processed = nil + do + (if (and (= (length arg) 3) (eq (third arg) :out)) + (push (list (first arg) + (list :reference-return (second arg))) processed) + (push (subseq arg 0 2) processed)) + finally (return processed))) + +(defun preprocess-names (names) + (let ((fname (gensym))) + (if (atom names) + (values (list names fname) fname (uffi::make-lisp-name names)) + (values (list (first names) fname) fname (second names))))) + +(defun preprocess-args (args) + (loop for arg in args + with lisp-args = nil and out = nil and processed = nil + do + (if (= (length arg) 3) + (ecase (third arg) + (:in + (progn + (push (first arg) lisp-args) + (push (list (first arg) (second arg)) processed))) + (:out + (progn + (push (list (first arg) (second arg)) out) + (push (list (first arg) (list '* (second arg))) processed)))) + (progn + (push (first arg) lisp-args) + (push arg processed))) + finally (return (values (nreverse lisp-args) + (nreverse out) + (nreverse processed))))) + + +(defmacro def-function (names args &key module returning) + (multiple-value-bind (lisp-args out processed) + (preprocess-args args) + (if (= (length out) 0) + `(%def-function ,names ,args + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + + #+(or cmu scl sbcl) + `(%def-function ,names ,args + ,@(if returning (list :returning returning) (values))) + #+lispworks + `(%def-function ,names ,(convert-lispworks-args args) + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + #-(or cmu scl sbcl lispworks) + (multiple-value-bind (name-pair fname lisp-name) + (preprocess-names names) + `(prog1 + (%def-function ,name-pair ,processed + :module ,module :returning ,returning) + ;(declaim (inline ,fname)) + (defun ,lisp-name ,lisp-args + (with-foreign-objects ,out + (values (,fname ,@(mapcar #'first args)) + ,@(mapcar #'(lambda (arg) + (list 'deref-pointer + (first arg) + (second arg))) out)))))) + ))) + + ;; name is either a string representing foreign name, or a list ;; of foreign-name as a string and lisp name as a symbol -(defmacro def-function (names args &key module returning) +(defmacro %def-function (names args &key module returning) #+(or cmu sbcl scl allegro mcl cormanlisp) (declare (ignore module)) (let* ((result-type (convert-from-uffi-type returning :return)) @@ -94,7 +200,7 @@ ,@(if module (list :module module) (values)) :result-type ,result-type :language :ansi-c - :calling-convention :cdecl) + #-macosx :calling-convention #-macosx :cdecl) #+(and mcl (not openmcl)) `(eval-when (:compile-toplevel :load-toplevel :execute) (ccl:define-entry-point (,lisp-name ,foreign-name) @@ -117,10 +223,5 @@ )) -(defun make-lisp-name (name) - (let ((converted (substitute #\- #\_ name))) - (intern - #+case-sensitive converted - #-case-sensitive (string-upcase converted))))