X-Git-Url: https://git.distorted.org.uk/~mdw/clg/blobdiff_plain/38c604ec4b161103576e1ecad95d67209da2967c..756b5b48cd58e3d8f1bb4c2fa8c44104a5d9ebed:/glib/gforeign.lisp?ds=sidebyside diff --git a/glib/gforeign.lisp b/glib/gforeign.lisp deleted file mode 100644 index 6f27b8a..0000000 --- a/glib/gforeign.lisp +++ /dev/null @@ -1,733 +0,0 @@ -;; Common Lisp bindings for GTK+ v2.0 -;; Copyright (C) 1999-2001 Espen S. Johnsen -;; -;; This library is free software; you can redistribute it and/or -;; modify it under the terms of the GNU Lesser General Public -;; License as published by the Free Software Foundation; either -;; version 2 of the License, or (at your option) any later version. -;; -;; This library is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; Lesser General Public License for more details. -;; -;; You should have received a copy of the GNU Lesser General Public -;; License along with this library; if not, write to the Free Software -;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -;; $Id: gforeign.lisp,v 1.14 2002-04-02 14:52:25 espen Exp $ - -(in-package "GLIB") - -;;;; Type methods - -(defvar *type-methods* (make-hash-table)) - -(defun ensure-type-method-fun (fname) - (unless (fboundp fname) - (setf - (symbol-function fname) - #'(lambda (type-spec &rest args) - (apply - (find-applicable-type-method type-spec fname) type-spec args))))) - -(defmacro define-type-method-fun (fname lambda-list) - (declare (ignore lambda-list)) - `(defun ,fname (type-spec &rest args) - (apply - (find-applicable-type-method type-spec ',fname) type-spec args))) - - -(defun ensure-type-name (type) - (etypecase type - (symbol type) - (pcl::class (class-name type)))) - -(defun add-type-method (type fname function) - (push - (cons fname function) - (gethash (ensure-type-name type) *type-methods*))) - -(defun find-type-method (type fname) - (cdr (assoc fname (gethash (ensure-type-name type) *type-methods*)))) - -(defun find-applicable-type-method (type-spec fname &optional (error t)) - (flet ((find-superclass-method (class) - (when (and class (class-finalized-p class)) -; (unless (class-finalized-p class) -; (finalize-inheritance class)) - (dolist (super (cdr (pcl::class-precedence-list class))) - (return-if (find-type-method super fname))))) - (find-expanded-type-method (type-spec) - (multiple-value-bind (expanded-type-spec expanded-p) - (type-expand-1 type-spec) - (cond - (expanded-p - (find-applicable-type-method expanded-type-spec fname nil)) - ((neq type-spec t) - (find-applicable-type-method t fname nil)))))) - - (or - (typecase type-spec - (pcl::class - (or - (find-type-method type-spec fname) - (find-superclass-method type-spec))) - (symbol - (or - (find-type-method type-spec fname) - (find-expanded-type-method type-spec) - (find-superclass-method (find-class type-spec nil)))) - (cons - (or - (find-type-method (first type-spec) fname) - (find-expanded-type-method type-spec))) - (t - (error "Invalid type specifier ~A" type-spec))) - (and - error - (error - "No applicable method for ~A when called with type specifier ~A" - fname type-spec))))) - -(defmacro deftype-method (fname type lambda-list &body body) - `(progn - (ensure-type-method-fun ',fname) - (add-type-method ',type ',fname #'(lambda ,lambda-list ,@body)) - ',fname)) - -;; To make the compiler happy -(eval-when (:compile-toplevel :load-toplevel :execute) - (define-type-method-fun translate-type-spec (type-spec)) - (define-type-method-fun size-of (type-spec)) - (define-type-method-fun translate-to-alien (type-spec expr &optional weak-ref)) - (define-type-method-fun translate-from-alien (type-spec expr &optional weak-ref)) - (define-type-method-fun cleanup-alien (type-spec sap &otional weak-ref)) - (define-type-method-fun unreference-alien (type-spec sap))) - - -;;;; - -(defvar *type-function-cache* (make-hash-table :test #'equal)) - -(defun get-cached-function (type-spec fname) - (cdr (assoc fname (gethash type-spec *type-function-cache*)))) - -(defun set-cached-function (type-spec fname function) - (push (cons fname function) (gethash type-spec *type-function-cache*)) - function) - - -(defun intern-argument-translator (type-spec) - (or - (get-cached-function type-spec 'argument-translator) - (set-cached-function type-spec 'argument-translator - (compile - nil - `(lambda (object) - (declare (ignorable object)) - ,(translate-to-alien type-spec 'object t)))))) - -(defun intern-return-value-translator (type-spec) - (or - (get-cached-function type-spec 'return-value-translator) - (set-cached-function type-spec 'return-value-translator - (compile - nil - `(lambda (alien) - (declare (ignorable alien)) - ,(translate-from-alien type-spec 'alien nil)))))) - -(defun intern-cleanup-function (type-spec) - (or - (get-cached-function type-spec 'cleanup-function) - (set-cached-function type-spec 'cleanup-function - (compile - nil - `(lambda (alien) - (declare (ignorable alien)) - ,(cleanup-alien type-spec 'alien t)))))) - - - -;; Returns a function to write an object of the specified type -;; to a memory location -(defun intern-writer-function (type-spec) - (or - (get-cached-function type-spec 'writer-function) - (set-cached-function type-spec 'writer-function - (compile - nil - `(lambda (value sap offset) - (declare (ignorable value sap offset)) - (setf - (,(sap-ref-fname type-spec) sap offset) - ,(translate-to-alien type-spec 'value nil))))))) - -;; Returns a function to read an object of the specified type -;; from a memory location -(defun intern-reader-function (type-spec) - (or - (get-cached-function type-spec 'reader-function) - (set-cached-function type-spec 'reader-function - (compile - nil - `(lambda (sap offset) - (declare (ignorable sap offset)) - ,(translate-from-alien - type-spec `(,(sap-ref-fname type-spec) sap offset) t)))))) - -(defun intern-destroy-function (type-spec) - (if (atomic-type-p type-spec) - #'(lambda (sap offset) - (declare (ignore sap offset))) - (or - (get-cached-function type-spec 'destroy-function) - (set-cached-function type-spec 'destroy-function - (compile - nil - `(lambda (sap offset) - (declare (ignorable sap offset)) - ,(unreference-alien - type-spec `(,(sap-ref-fname type-spec) sap offset)))))))) - - - -;;;; - -(defconstant +bits-per-unit+ 8 - "Number of bits in an addressable unit (byte)") - -;; Sizes of fundamental C types in addressable units -(defconstant +size-of-short+ 2) -(defconstant +size-of-int+ 4) -(defconstant +size-of-long+ 4) -(defconstant +size-of-sap+ 4) -(defconstant +size-of-float+ 4) -(defconstant +size-of-double+ 8) - -(defun sap-ref-unsigned (sap offset) - (sap-ref-32 sap offset)) - -(defun sap-ref-signed (sap offset) - (signed-sap-ref-32 sap offset)) - -(defun sap-ref-fname (type-spec) - (let ((alien-type-spec (mklist (translate-type-spec type-spec)))) - (ecase (first alien-type-spec) - (unsigned - (ecase (second alien-type-spec) - (8 'sap-ref-8) - (16 'sap-ref-16) - (32 'sap-ref-32) - (64 'sap-ref-64))) - (signed - (ecase (second alien-type-spec) - (8 'signed-sap-ref-8) - (16 'signed-sap-ref-16) - (32 'signed-sap-ref-32) - (64 'signed-sap-ref-64))) - (system-area-pointer 'sap-ref-sap) - (single-float 'sap-ref-single) - (double-float 'sap-ref-double)))) - - -;;;; Foreign function call interface - -(defvar *package-prefix* nil) - -(defun set-package-prefix (prefix &optional (package *package*)) - (let ((package (find-package package))) - (delete-if #'(lambda (assoc) (eq (car assoc) package)) *package-prefix*) - (push (cons package prefix) *package-prefix*)) - prefix) - -(defun package-prefix (&optional (package *package*)) - (let ((package (find-package package))) - (or - (cdr (assoc package *package-prefix*)) - (substitute #\_ #\- (string-downcase (package-name package)))))) - -(defun find-prefix-package (prefix) - (or - (car (rassoc (string-downcase prefix) *package-prefix* :test #'string=)) - (find-package (string-upcase prefix)))) - -(defmacro use-prefix (prefix &optional (package *package*)) - `(eval-when (:compile-toplevel :load-toplevel :execute) - (set-package-prefix ,prefix ,package))) - - -(defun default-alien-fname (lisp-name) - (let* ((lisp-name-string - (if (char= (char (the simple-string (string lisp-name)) 0) #\%) - (subseq (the simple-string (string lisp-name)) 1) - (string lisp-name))) - (prefix (package-prefix *package*)) - (name (substitute #\_ #\- (string-downcase lisp-name-string)))) - (if (or (not prefix) (string= prefix "")) - name - (format nil "~A_~A" prefix name)))) - -(defun default-alien-type-name (type-name) - (let ((prefix (package-prefix *package*))) - (apply - #'concatenate - 'string - (mapcar - #'string-capitalize - (cons prefix (split-string (symbol-name type-name) #\-)))))) - -(defun default-type-name (alien-name) - (let ((parts - (mapcar - #'string-upcase - (split-string-if alien-name #'upper-case-p)))) - (intern - (concatenate-strings - (rest parts) #\-) (find-prefix-package (first parts))))) - - -(defmacro defbinding (name lambda-list return-type-spec &rest docs/args) - (multiple-value-bind (lisp-name c-name) - (if (atom name) - (values name (default-alien-fname name)) - (values-list name)) - - (let ((supplied-lambda-list lambda-list) - (docs nil) - (args nil)) - (dolist (doc/arg docs/args) - (if (stringp doc/arg) - (push doc/arg docs) - (progn - (destructuring-bind (expr type &optional (style :in)) doc/arg - (unless (member style '(:in :out :in-out)) - (error "Bogus argument style ~S in ~S." style doc/arg)) - (when (and - (not supplied-lambda-list) - (namep expr) (member style '(:in :in-out))) - (push expr lambda-list)) - (push - (list (if (namep expr) expr (gensym)) expr type style) args))))) - - (%defbinding - c-name lisp-name (or supplied-lambda-list (nreverse lambda-list)) - return-type-spec (reverse docs) (reverse args))))) - -#+cmu -(defun %defbinding (foreign-name lisp-name lambda-list - return-type-spec docs args) - (ext:collect ((alien-types) (alien-bindings) (alien-parameters) - (alien-values) (alien-deallocators)) - (dolist (arg args) - (destructuring-bind (var expr type-spec style) arg - (let ((declaration (translate-type-spec type-spec)) - (deallocation (cleanup-alien type-spec var t))) - (cond - ((member style '(:out :in-out)) - (alien-types `(* ,declaration)) - (alien-parameters `(addr ,var)) - (alien-bindings - `(,var ,declaration - ,@(when (eq style :in-out) - (list (translate-to-alien type-spec expr t))))) - (alien-values (translate-from-alien type-spec var nil))) - (deallocation - (alien-types declaration) - (alien-bindings - `(,var ,declaration ,(translate-to-alien type-spec expr t))) - (alien-parameters var) - (alien-deallocators deallocation)) - (t - (alien-types declaration) - (alien-parameters (translate-to-alien type-spec expr t))))))) - - (let ((alien-funcall `(alien-funcall ,lisp-name ,@(alien-parameters)))) - `(defun ,lisp-name ,lambda-list - ,@docs - (declare (optimize (ext:inhibit-warnings 3))) - (with-alien ((,lisp-name - (function - ,(translate-type-spec return-type-spec) - ,@(alien-types)) - :extern ,foreign-name) - ,@(alien-bindings)) - ,(if return-type-spec - `(let ((result - ,(translate-from-alien return-type-spec alien-funcall nil))) - ,@(alien-deallocators) - (values result ,@(alien-values))) - `(progn - ,alien-funcall - ,@(alien-deallocators) - (values ,@(alien-values))))))))) - - -(defun mkbinding (name return-type &rest arg-types) - (declare (optimize (ext:inhibit-warnings 3))) - (let* ((ftype - `(function - ,@(mapcar #'translate-type-spec (cons return-type arg-types)))) - (alien - (alien::%heap-alien - (alien::make-heap-alien-info - :type (alien::parse-alien-type ftype) - :sap-form (system:foreign-symbol-address name)))) - (translate-arguments - (mapcar #'intern-argument-translator arg-types)) - (translate-return-value (intern-return-value-translator return-type)) - (cleanup-arguments (mapcar #'intern-cleanup-function arg-types))) - - #'(lambda (&rest args) - (map-into args #'funcall translate-arguments args) - (prog1 - (funcall - translate-return-value (apply #'alien:alien-funcall alien args)) - (mapc #'funcall cleanup-arguments args))))) - - -(defun type-translateable-p (type-spec) - (find-applicable-type-method type-spec 'translate-type-spec nil)) - -(defun every-type-translateable-p (type-specs) - (every #'type-translateable-p type-specs)) - -(defun mkbinding-late (name return-type &rest arg-types) - (if (every-type-translateable-p (cons return-type arg-types)) - (apply #'mkbinding name return-type arg-types) - (let ((binding nil)) - #'(lambda (&rest args) - (cond - (binding (apply binding args)) - ((every-type-translateable-p (cons return-type arg-types)) - (setq binding (apply #'mkbinding name return-type arg-types)) - (apply binding args)) - (t - (dolist (type-spec (cons return-type arg-types)) - (unless (type-translateable-p type-spec) - (error "Can't translate type ~A" type-spec))))))))) - - - -;;;; Definitons and translations of fundamental types - -(deftype long (&optional (min '*) (max '*)) `(integer ,min ,max)) -(deftype unsigned-long (&optional (min '*) (max '*)) `(integer ,min ,max)) -(deftype int (&optional (min '*) (max '*)) `(long ,min ,max)) -(deftype unsigned-int (&optional (min '*) (max '*)) `(unsigned-long ,min ,max)) -(deftype short (&optional (min '*) (max '*)) `(int ,min ,max)) -(deftype unsigned-short (&optional (min '*) (max '*)) `(unsigned-int ,min ,max)) -(deftype signed (&optional (size '*)) `(signed-byte ,size)) -(deftype unsigned (&optional (size '*)) `(signed-byte ,size)) -(deftype char () 'base-char) -(deftype pointer () 'system-area-pointer) -(deftype boolean (&optional (size '*)) - (declare (ignore size)) - `(member t nil)) -(deftype invalid () nil) - -(defun atomic-type-p (type-spec) - (or - (eq type-spec 'pointer) - (not (eq (translate-type-spec type-spec) 'system-area-pointer)))) - - -(deftype-method cleanup-alien t (type-spec sap &optional weak-ref) - (declare (ignore type-spec sap weak-ref)) - nil) - - -(deftype-method translate-to-alien integer (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - -(deftype-method translate-from-alien integer (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - - -(deftype-method translate-type-spec fixnum (type-spec) - (declare (ignore type-spec)) - (translate-type-spec 'signed)) - -(deftype-method size-of fixnum (type-spec) - (declare (ignore type-spec)) - (size-of 'signed)) - -(deftype-method translate-to-alien fixnum (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - -(deftype-method translate-from-alien fixnum (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - - -(deftype-method translate-type-spec long (type-spec) - (declare (ignore type-spec)) - `(signed ,(* +bits-per-unit+ +size-of-long+))) - -(deftype-method size-of long (type-spec) - (declare (ignore type-spec)) - +size-of-long+) - - -(deftype-method translate-type-spec unsigned-long (type-spec) - (declare (ignore type-spec)) - `(unsigned ,(* +bits-per-unit+ +size-of-long+))) - -(deftype-method size-of unsigned-long (type-spec) - (declare (ignore type-spec)) - +size-of-long+) - - -(deftype-method translate-type-spec int (type-spec) - (declare (ignore type-spec)) - `(signed ,(* +bits-per-unit+ +size-of-int+))) - -(deftype-method size-of int (type-spec) - (declare (ignore type-spec)) - +size-of-int+) - - -(deftype-method translate-type-spec unsigned-int (type-spec) - (declare (ignore type-spec)) - `(unsigned ,(* +bits-per-unit+ +size-of-int+))) - -(deftype-method size-of unsigned-int (type-spec) - (declare (ignore type-spec)) - +size-of-int+) - - -(deftype-method translate-type-spec short (type-spec) - (declare (ignore type-spec)) - `(signed ,(* +bits-per-unit+ +size-of-short+))) - -(deftype-method size-of short (type-spec) - (declare (ignore type-spec)) - +size-of-short+) - - -(deftype-method translate-type-spec unsigned-short (type-spec) - (declare (ignore type-spec)) - `(unsigned ,(* +bits-per-unit+ +size-of-short+))) - -(deftype-method size-of unsigned-short (type-spec) - (declare (ignore type-spec)) - +size-of-short+) - - -(deftype-method translate-type-spec signed-byte (type-spec) - (let ((size (second (mklist (type-expand-to 'signed-byte type-spec))))) - `(signed - ,(cond - ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+)) - (t size))))) - -(deftype-method size-of signed-byte (type-spec) - (let ((size (second (mklist (type-expand-to 'signed-byte type-spec))))) - (cond - ((member size '(nil *)) +size-of-int+) - (t (/ size +bits-per-unit+))))) - -(deftype-method translate-to-alien signed-byte (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - -(deftype-method translate-from-alien signed-byte - (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - - -(deftype-method translate-type-spec unsigned-byte (type-spec) - (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec))))) - `(signed - ,(cond - ((member size '(nil *)) (* +bits-per-unit+ +size-of-int+)) - (t size))))) - -(deftype-method size-of unsigned-byte (type-spec) - (let ((size (second (mklist (type-expand-to 'unsigned-byte type-spec))))) - (cond - ((member size '(nil *)) +size-of-int+) - (t (/ size +bits-per-unit+))))) - -(deftype-method translate-to-alien unsigned-byte (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - -(deftype-method translate-from-alien unsigned-byte - (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - - -(deftype-method translate-type-spec single-float (type-spec) - (declare (ignore type-spec)) - 'single-float) - -(deftype-method size-of single-float (type-spec) - (declare (ignore type-spec)) - +size-of-float+) - -(deftype-method translate-to-alien single-float (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - -(deftype-method translate-from-alien single-float - (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - - -(deftype-method translate-type-spec double-float (type-spec) - (declare (ignore type-spec)) - 'double-float) - -(deftype-method size-of double-float (type-spec) - (declare (ignore type-spec)) - +size-of-double+) - -(deftype-method translate-to-alien double-float (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - -(deftype-method translate-from-alien double-float - (type-spec number &optional weak-ref) - (declare (ignore type-spec weak-ref)) - number) - - -(deftype-method translate-type-spec base-char (type-spec) - (declare (ignore type-spec)) - `(unsigned ,+bits-per-unit+)) - -(deftype-method size-of base-char (type-spec) - (declare (ignore type-spec)) - 1) - -(deftype-method translate-to-alien base-char (type-spec char &optional weak-ref) - (declare (ignore type-spec weak-ref)) - `(char-code ,char)) - -(deftype-method translate-from-alien base-char (type-spec code &optional weak-ref) - (declare (ignore type-spec weak-ref)) - `(code-char ,code)) - - -(deftype-method translate-type-spec string (type-spec) - (declare (ignore type-spec)) - 'system-area-pointer) - -(deftype-method size-of string (type-spec) - (declare (ignore type-spec)) - +size-of-sap+) - -(deftype-method translate-to-alien string (type-spec string &optional weak-ref) - (declare (ignore type-spec weak-ref)) - `(let ((string ,string)) - ;; Always copy strings to prevent seg fault due to GC - (copy-memory - (make-pointer (1+ (kernel:get-lisp-obj-address string))) - (1+ (length string))))) - -(deftype-method translate-from-alien string - (type-spec c-string &optional weak-ref) - (declare (ignore type-spec)) - `(let ((c-string ,c-string)) - (unless (null-pointer-p c-string) - (prog1 - (c-call::%naturalize-c-string c-string) - ;,(unless weak-ref `(deallocate-memory c-string)) - )))) - -(deftype-method cleanup-alien string (type-spec c-string &optional weak-ref) - (when weak-ref - (unreference-alien type-spec c-string))) - -(deftype-method unreference-alien string (type-spec c-string) - (declare (ignore type-spec)) - `(let ((c-string ,c-string)) - (unless (null-pointer-p c-string) - (deallocate-memory c-string)))) - - -(deftype-method translate-type-spec boolean (type-spec) - (translate-type-spec - (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec)))))) - -(deftype-method size-of boolean (type-spec) - (size-of - (cons 'unsigned (cdr (mklist (type-expand-to 'boolean type-spec)))))) - -(deftype-method translate-to-alien boolean (type-spec boolean &optional weak-ref) - (declare (ignore type-spec weak-ref)) - `(if ,boolean 1 0)) - -(deftype-method translate-from-alien boolean (type-spec int &optional weak-ref) - (declare (ignore type-spec weak-ref)) - `(not (zerop ,int))) - - -(deftype-method translate-type-spec or (union-type) - (let* ((member-types (cdr (type-expand-to 'or union-type))) - (alien-type (translate-type-spec (first member-types)))) - (dolist (type (cdr member-types)) - (unless (eq alien-type (translate-type-spec type)) - (error "No common alien type specifier for union type: ~A" union-type))) - alien-type)) - -(deftype-method size-of or (union-type) - (size-of (first (cdr (type-expand-to 'or union-type))))) - -(deftype-method translate-to-alien or (union-type-spec expr &optional weak-ref) - (destructuring-bind (name &rest type-specs) - (type-expand-to 'or union-type-spec) - (declare (ignore name)) - `(let ((value ,expr)) - (etypecase value - ,@(map - 'list - #'(lambda (type-spec) - (list type-spec (translate-to-alien type-spec 'value weak-ref))) - type-specs))))) - - -(deftype-method translate-type-spec system-area-pointer (type-spec) - (declare (ignore type-spec)) - 'system-area-pointer) - -(deftype-method size-of system-area-pointer (type-spec) - (declare (ignore type-spec)) - +size-of-sap+) - -(deftype-method translate-to-alien system-area-pointer (type-spec sap &optional weak-ref) - (declare (ignore type-spec weak-ref)) - sap) - -(deftype-method translate-from-alien system-area-pointer - (type-spec sap &optional weak-ref) - (declare (ignore type-spec weak-ref)) - sap) - - -(deftype-method translate-type-spec null (type-spec) - (declare (ignore type-spec)) - 'system-area-pointer) - -(deftype-method translate-to-alien null (type-spec expr &optional weak-ref) - (declare (ignore type-spec expr weak-ref)) - `(make-pointer 0)) - - -(deftype-method translate-type-spec nil (type-spec) - (declare (ignore type-spec)) - 'void) - -(deftype-method translate-from-alien nil (type-spec expr &optional weak-ref) - (declare (ignore type-spec weak-ref)) - `(progn - ,expr - (values)))