;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: basic-types.lisp,v 1.1 2006-04-25 20:36:05 espen Exp $
+;; $Id: basic-types.lisp,v 1.2 2006-06-08 13:24:25 espen Exp $
(in-package "GFFI")
(define-type-generic size-of (type &key inlined)
"Returns the foreign size of TYPE. The default value of INLINED is
T for basic C types and NIL for other types.")
+(define-type-generic type-alignment (type &key inlined)
+ "Returns the alignment of TYPE. The default value of INLINED is
+T for basic C types and NIL for other types.")
(define-type-generic alien-arg-wrapper (type var arg style form &optional copy-p)
"Creates a wrapper around FORM which binds the alien translation of
ARG to VAR in a way which makes it possible to pass the location of
(declare (ignore type))
(size-of 'signed-byte :inlined inlined))
+(define-type-method type-alignment ((type integer) &key (inlined t))
+ (declare (ignore type))
+ (type-alignment 'signed-byte :inlined inlined))
+
(define-type-method writer-function ((type integer) &key temp (inlined t))
(declare (ignore temp))
(assert-inlined type inlined)
(32 4)
(64 8)))))
+(define-type-method type-alignment ((type signed-byte) &key (inlined t))
+ (assert-inlined type inlined)
+ (destructuring-bind (&optional (size '*))
+ (rest (mklist (type-expand-to 'signed-byte type)))
+ (let ((size (if (eq size '*)
+ (second (type-expand-to 'signed-byte 'int))
+ size)))
+ #+sbcl(sb-alignment `(sb-alien:signed ,size))
+ #+clisp(ecase size
+ ( 8 (nth-value 1 (ffi:sizeof 'ffi:sint8)))
+ (16 (nth-value 1 (ffi:sizeof 'ffi:sint16)))
+ (32 (nth-value 1 (ffi:sizeof 'ffi:sint32)))
+ (64 (nth-value 1 (ffi:sizeof 'ffi:sint64))))
+ #-(or sbcl clisp) 4)))
+
(define-type-method writer-function ((type signed-byte) &key temp (inlined t))
(declare (ignore temp))
(assert-inlined type inlined)
(rest (mklist (type-expand-to 'unsigned-byte type)))
(size-of `(signed ,size))))
+(define-type-method type-alignment ((type unsigned-byte) &key (inlined t))
+ (assert-inlined type inlined)
+ (destructuring-bind (&optional (size '*))
+ (rest (mklist (type-expand-to 'unsigned-byte type)))
+ (type-alignment `(signed ,size))))
+
(define-type-method writer-function ((type unsigned-byte) &key temp (inlined t))
(declare (ignore temp))
(assert-inlined type inlined)
#+clisp (ffi:sizeof 'single-float)
#-(or sbcl clisp) 4)
+(define-type-method type-alignment ((type single-float) &key (inlined t))
+ (assert-inlined type inlined)
+ #+sbcl (sb-alignment 'single-float)
+ #+clisp (nth-value 1 (ffi:sizeof 'single-float))
+ #-(or sbcl clisp) 4)
+
(define-type-method to-alien-form ((type single-float) form &optional copy-p)
(declare (ignore type copy-p))
`(coerce ,form 'single-float))
#+clisp (ffi:sizeof 'double-float)
#-(or sbcl clisp) 8)
+(define-type-method type-alignment ((type double-float) &key (inlined t))
+ (assert-inlined type inlined)
+ #+sbcl (sb-alignment 'double-float)
+ #+clisp (nth-value 1 (ffi:sizeof 'double-float))
+ #-(or sbcl clisp) 4)
+
(define-type-method to-alien-form ((type double-float) form &optional copy-p)
(declare (ignore type copy-p))
`(coerce ,form 'double-float))
(define-type-method size-of ((type base-char) &key (inlined t))
(assert-inlined type inlined)
1)
+
+(define-type-method type-alignment ((type base-char) &key (inlined t))
+ (assert-inlined type inlined)
+ #+sbcl (sb-alignment 'sb-alien:char)
+ #+clisp (nth-value 1 (ffi:sizeof 'ffi:character))
+ #-(or sbcl clisp) 4)
(define-type-method to-alien-form ((type base-char) form &optional copy-p)
(declare (ignore type copy-p))
(assert-not-inlined type inlined)
(size-of 'pointer))
+(define-type-method type-alignment ((type string) &key inlined)
+ (assert-not-inlined type inlined)
+ (type-alignment 'pointer))
+
(define-type-method to-alien-form ((type string) string &optional copy-p)
(declare (ignore type copy-p))
`(encode-utf8-string ,string))
(assert-not-inlined type inlined)
(size-of 'string))
+(define-type-method type-alignment ((type pathname) &key inlined)
+ (assert-not-inlined type inlined)
+ (type-alignment 'string))
+
(define-type-method alien-arg-wrapper ((type pathname) var pathname style form &optional copy-in-p)
(declare (ignore type))
(alien-arg-wrapper 'string var `(namestring (translate-logical-pathname ,pathname)) style form copy-in-p))
(rest (mklist (type-expand-to 'bool type)))
(size-of `(signed-byte ,size))))
+(define-type-method type-alignment ((type bool) &key (inlined t))
+ (assert-inlined type inlined)
+ (destructuring-bind (&optional (size '*))
+ (rest (mklist (type-expand-to 'bool type)))
+ (type-alignment `(signed-byte ,size))))
+
(define-type-method to-alien-form ((type bool) bool &optional copy-p)
(declare (ignore type copy-p))
`(if ,bool 1 0))
(assert-inlined type inlined)
(size-of 'bool))
+(define-type-method type-alignment ((type boolean) &key (inlined t))
+ (assert-inlined type inlined)
+ (type-alignment 'bool))
+
(define-type-method to-alien-form ((type boolean) boolean &optional copy-p)
(declare (ignore type copy-p))
(to-alien-form 'bool boolean))
(size-of subtype inlined)
(size-of subtype))))
+(define-type-method type-alignment ((type or) &key (inlined nil inlined-p))
+ (loop
+ for subtype in (type-expand-to 'or type)
+ maximize (if inlined-p
+ (type-alignment subtype inlined)
+ (type-alignment subtype))))
+
(define-type-method alien-arg-wrapper ((type or) var value style form &optional copy-in-p)
(cond
((and (in-arg-p style) (out-arg-p style))
#+clisp (ffi:sizeof 'ffi:c-pointer)
#-(or sbcl clisp) 4)
+(define-type-method type-alignment ((type pointer) &key (inlined t))
+ (assert-inlined type inlined)
+ #+sbcl (sb-alignment 'system-area-pointer)
+ #+clisp (ffi:sizeof 'ffi:c-pointer)
+ #-(or sbcl clisp) (size-of 'pointer))
+
(define-type-method to-alien-form ((type pointer) form &optional copy-p)
(declare (ignore type copy-p))
form)
(assert-inlined type inlined)
(size-of (second (type-expand-to 'inlined type)) :inlined t))
+(define-type-method type-alignment ((type inlined) &key (inlined t))
+ (assert-inlined type inlined)
+ (type-alignment (second (type-expand-to 'inlined type)) :inlined t))
+
(define-type-method reader-function ((type inlined) &key (ref :read) (inlined t))
(assert-inlined type inlined)
(reader-function (second (type-expand-to 'inlined type)) :ref ref :inlined t))
;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: defpackage.lisp,v 1.1 2006-04-25 20:29:14 espen Exp $
+;; $Id: defpackage.lisp,v 1.2 2006-06-08 13:24:25 espen Exp $
(defpackage "GFFI"
(:use "COMMON-LISP" "AUTOEXPORT" "PKG-CONFIG" "CLG-UTILS")
"DEFAULT-ALIEN-TYPE-NAME" "DEFAULT-TYPE-NAME" "TYPE-EXPAND"
"TYPE-EXPAND-1" "TYPE-EXPAND-TO")
;; Symbols from basic-types.lisp
- (:export "LONG" "UNSIGNED-LONG" "INT" "UNSIGNED-INT" "SHORT"
- "UNSIGNED-SHORT" "SIGNED" "UNSIGNED" "CHAR" "POINTER"
- "BOOL" "COPY-OF" "STATIC" "SIZE-OF" "ALIEN-TYPE" "UNBOUND-VALUE"
+ (:export "LONG" "UNSIGNED-LONG" "INT" "UNSIGNED-INT" "SHORT" "UNSIGNED-SHORT"
+ "SIGNED" "UNSIGNED" "CHAR" "POINTER" "BOOL" "COPY-OF" "STATIC"
+ "SIZE-OF" "TYPE-ALIGNMENT" "ALIEN-TYPE" "UNBOUND-VALUE"
"ALIEN-ARG-WRAPPER" "TO-ALIEN-FORM" "FROM-ALIEN-FORM"
"CALLBACK-WRAPPER" "TO-ALIEN-FUNCTION" "FROM-ALIEN-FUNCTION"
"READER-FUNCTION" "WRITER-FUNCTION" "GETTER-FUNCTION"
;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: enums.lisp,v 1.1 2006-04-25 20:37:49 espen Exp $
+;; $Id: enums.lisp,v 1.2 2006-06-08 13:24:25 espen Exp $
(in-package "GFFI")
(assert-inlined type inlined)
(size-of 'signed))
+(define-type-method type-alignment ((type enum) &key (inlined t))
+ (assert-inlined type inlined)
+ (type-alignment 'signed))
+
(define-type-method to-alien-form ((type enum) form &optional copy-p)
(declare (ignore copy-p))
`(case ,form
(assert-inlined type inlined)
(size-of 'unsigned))
+(define-type-method type-alignment ((type flags) &key (inlined t))
+ (assert-inlined type inlined)
+ (type-alignment 'unsigned))
+
(define-type-method to-alien-form ((type flags) flags &optional copy-p)
(declare (ignore copy-p))
`(reduce #'logior (mklist ,flags)
(let ((flags-int (intern (format nil "~A-TO-INT" name)))
(int-flags (intern (format nil "INT-TO-~A" name)))
(satisfies (intern (format nil "~A-P" name))))
- `(progn
+ `(eval-when (:compile-toplevel :load-toplevel :execute)
(deftype ,name () '(satisfies ,satisfies))
(defun ,satisfies (object)
(flet ((valid-p (ob)
for (int symbol) in ',(%map-flags args :int-symbol)
when(= (logand value int) int)
collect symbol))
- (eval-when (:compile-toplevel :load-toplevel :execute)
- (define-type-method alien-type ((type ,name))
- (declare (ignore type))
- (alien-type 'flags))
- (define-type-method size-of ((type ,name) &key (inlined t))
- (assert-inlined type inlined)
- (size-of 'flags))
- (define-type-method to-alien-form ((type ,name) form &optional copy-p)
- (declare (ignore type copy-p))
- (list ',flags-int form))
- (define-type-method from-alien-form ((type ,name) form &key ref)
- (declare (ignore type ref))
- (list ',int-flags form))
- (define-type-method to-alien-function ((type ,name) &optional copy-p)
- (declare (ignore type copy-p))
- #',flags-int)
- (define-type-method from-alien-function ((type ,name) &key ref)
- (declare (ignore type ref))
- #',int-flags)
- (define-type-method writer-function ((type ,name) &key temp (inlined t))
- (declare (ignore temp))
- (assert-inlined type inlined)
- (let ((writer (writer-function 'signed)))
- #'(lambda (flags location &optional (offset 0))
- (funcall writer (,flags-int flags) location offset))))
- (define-type-method reader-function ((type ,name) &key ref (inlined t))
- (declare (ignore ref))
- (assert-inlined type inlined)
- (let ((reader (reader-function 'signed)))
- #'(lambda (location &optional (offset 0))
- (,int-flags (funcall reader location offset)))))))))
+ (define-type-method alien-type ((type ,name))
+ (declare (ignore type))
+ (alien-type 'flags))
+ (define-type-method size-of ((type ,name) &key (inlined t))
+ (assert-inlined type inlined)
+ (size-of 'flags))
+ (define-type-method type-alignment ((type ,name) &key (inlined t))
+ (assert-inlined type inlined)
+ (type-alignment 'flags))
+ (define-type-method to-alien-form ((type ,name) form &optional copy-p)
+ (declare (ignore type copy-p))
+ (list ',flags-int form))
+ (define-type-method from-alien-form ((type ,name) form &key ref)
+ (declare (ignore type ref))
+ (list ',int-flags form))
+ (define-type-method to-alien-function ((type ,name) &optional copy-p)
+ (declare (ignore type copy-p))
+ #',flags-int)
+ (define-type-method from-alien-function ((type ,name) &key ref)
+ (declare (ignore type ref))
+ #',int-flags)
+ (define-type-method writer-function ((type ,name) &key temp (inlined t))
+ (declare (ignore temp))
+ (assert-inlined type inlined)
+ (let ((writer (writer-function 'signed)))
+ #'(lambda (flags location &optional (offset 0))
+ (funcall writer (,flags-int flags) location offset))))
+ (define-type-method reader-function ((type ,name) &key ref (inlined t))
+ (declare (ignore ref))
+ (assert-inlined type inlined)
+ (let ((reader (reader-function 'signed)))
+ #'(lambda (location &optional (offset 0))
+ (,int-flags (funcall reader location offset))))))))
(defexport define-enum-type (name &rest args)
;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: memory.lisp,v 1.1 2006-04-25 20:31:35 espen Exp $
+;; $Id: memory.lisp,v 1.2 2006-06-08 13:24:25 espen Exp $
(in-package "GFFI")
(sb-alien-internals:parse-alien-type type nil)))
(defun sb-sizeof (type)
- (/ (sb-sizeof-bits type) 8)))
+ (/ (sb-sizeof-bits type) 8))
+
+ (defun sb-alignment (type)
+ (/ (sb-alien-internals:alien-type-alignment
+ (sb-alien-internals:parse-alien-type type nil))
+ 8)))
;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: proxy.lisp,v 1.1 2006-04-25 20:49:16 espen Exp $
+;; $Id: proxy.lisp,v 1.2 2006-06-08 13:25:09 espen Exp $
(in-package "GFFI")
(funcall writer (foreign-location object) value)))
(call-next-method)))
- (defconstant +struct-alignmen+ (size-of 'pointer))
-
- (defun align-offset (size &optional packed-p)
- (if (or packed-p (zerop (mod size +struct-alignmen+)))
- size
- (+ size (- +struct-alignmen+ (mod size +struct-alignmen+)))))
+ (defun adjust-offset (offset type &optional packed-p)
+ (let ((alignment (type-alignment type)))
+ (if (or packed-p (zerop (mod offset alignment)))
+ offset
+ (+ offset (- alignment (mod offset alignment))))))
(defmethod compute-slots ((class proxy-class))
(let ((alien-slots (remove-if-not
(when alien-slots
(loop
with packed-p = (foreign-slots-packed-p class)
- as offset = (align-offset
+ for slotd in alien-slots
+ as offset = (adjust-offset
(foreign-size (most-specific-proxy-superclass class))
+ (slot-definition-type slotd)
packed-p)
- then (align-offset
- (+
- (slot-definition-offset slotd)
- (size-of (slot-definition-type slotd)))
- packed-p)
- for slotd in alien-slots
- unless (slot-boundp slotd 'offset)
- do (setf (slot-value slotd 'offset) offset))))
+ then (adjust-offset offset (slot-definition-type slotd) packed-p)
+ do (if (slot-boundp slotd 'offset)
+ (setf offset (slot-value slotd 'offset))
+ (setf (slot-value slotd 'offset) offset))
+ (incf offset (size-of (slot-definition-type slotd))))))
(call-next-method))
(defmethod validate-superclass ((class proxy-class) (super standard-class))
(assert-not-inlined type inlined)
(size-of 'pointer))
+(define-type-method type-alignment ((type proxy) &key inlined)
+ (assert-not-inlined type inlined)
+ (type-alignment 'pointer))
+
(define-type-method from-alien-form ((type proxy) form &key (ref :free))
(let ((class (type-expand type)))
(ecase ref
(funcall ref (foreign-location instance))))
#'foreign-location))
-(define-type-method size-of ((type proxy) &key inlined)
- (assert-not-inlined type inlined)
- (size-of 'pointer))
-
(define-type-method writer-function ((type proxy) &key temp inlined)
(assert-not-inlined type inlined)
(if temp
(when (and
#?-(or (sbcl>= 0 9 8) (featurep :clisp))(class-finalized-p class)
(not (slot-boundp class 'size)))
- (let ((size (or
- (loop
- for slotd in slots
- when (eq (slot-definition-allocation slotd) :alien)
- maximize (+
- (slot-definition-offset slotd)
- (size-of (slot-definition-type slotd))))
- 0)))
- (setf (slot-value class 'size) (+ size (mod size +struct-alignmen+)))))
+ (setf (slot-value class 'size)
+ (or
+ (loop
+ for slotd in slots
+ when (eq (slot-definition-allocation slotd) :alien)
+ maximize (+
+ (slot-definition-offset slotd)
+ (size-of (slot-definition-type slotd))))
+ 0)))
slots))
(define-type-method callback-wrapper ((type struct) var arg form)
(foreign-size type)
(size-of 'pointer)))
+(define-type-method type-alignment ((type struct) &key inlined)
+ (if inlined
+ (let ((slot1 (find-if
+ #'(lambda (slotd)
+ (eq (slot-definition-allocation slotd) :alien))
+ (class-slots (find-class type)))))
+ (type-alignment (slot-definition-type slot1)))
+ (type-alignment 'pointer)))
+
(define-type-method writer-function ((type struct) &key temp inlined)
(if inlined
(if temp
;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: vectors.lisp,v 1.1 2006-04-25 20:40:57 espen Exp $
+;; $Id: vectors.lisp,v 1.2 2006-06-08 13:24:25 espen Exp $
(in-package "GFFI")
(* (size-of element-type) length)))
(size-of 'pointer)))
+(define-type-method type-alignment ((type vector) &key inlined)
+ (if inlined
+ (destructuring-bind (element-type &optional (length '*))
+ (rest (type-expand-to 'vector type))
+ (if (eq length '*)
+ (error "Can't inline vector with variable size: ~A" type)
+ (* (type-alignment element-type) length)))
+ (type-alignment 'pointer)))
+
(define-type-method alien-arg-wrapper ((type vector) var vector style form &optional copy-in-p)
(destructuring-bind (element-type &optional (length '*))
(rest (type-expand-to 'vector type))
(assert-not-inlined type inlined)
(size-of 'pointer))
+(define-type-method type-alignment ((type vector0) &key inlined)
+ (assert-not-inlined type inlined)
+ (type-alignment 'pointer))
+
(define-type-method alien-arg-wrapper ((type vector0) var vector style form &optional copy-in-p)
(destructuring-bind (element-type) (rest (type-expand-to 'vector0 type))
(cond
(assert-not-inlined type inlined)
(size-of 'pointer))
+(define-type-method type-alignment ((type counted-vector) &key inlined)
+ (assert-not-inlined type inlined)
+ (type-alignment 'pointer))
+
(define-type-method alien-arg-wrapper ((type counted-vector) var vector style form &optional copy-in-p)
(destructuring-bind (element-type &optional (counter-type 'unsigned-int))
(rest (type-expand-to 'counted-vector type))
;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;; $Id: glib.lisp,v 1.37 2006-04-25 21:51:32 espen Exp $
+;; $Id: glib.lisp,v 1.38 2006-06-08 13:24:25 espen Exp $
(in-package "GLIB")
(assert-not-inlined type inlined)
(size-of 'pointer))
+(define-type-method type-alignment ((type glist) &key inlined)
+ (assert-not-inlined type inlined)
+ (type-alignment 'pointer))
(define-type-method alien-arg-wrapper ((type glist) var list style form &optional copy-in-p)
(destructuring-bind (element-type) (rest (type-expand-to 'glist type))
(assert-not-inlined type inlined)
(size-of 'pointer))
+(define-type-method type-alignment ((type gslist) &key inlined)
+ (assert-not-inlined type inlined)
+ (type-alignment 'pointer))
+
(define-type-method alien-arg-wrapper ((type gslist) var list style form &optional copy-in-p)
(destructuring-bind (element-type) (rest (type-expand-to 'gslist type))
(cond