90 lines
4.0 KiB
Scheme
90 lines
4.0 KiB
Scheme
|
|
(define-record-type <pffi-struct>
|
|
(struct-make name size pointer members)
|
|
pffi-struct?
|
|
(name pffi-struct-name)
|
|
(size pffi-struct-size)
|
|
(pointer pffi-struct-pointer)
|
|
(members pffi-struct-members))
|
|
|
|
(define pffi-align-of
|
|
(lambda (type)
|
|
(cond-expand
|
|
;(guile (alignof (pffi-type->native-type type)))
|
|
(else (pffi-size-of type)))))
|
|
|
|
(define (round-to-next-modulo-of to-round roundee)
|
|
(if (= (floor-remainder to-round roundee) 0)
|
|
to-round
|
|
(round-to-next-modulo-of (+ to-round 1) roundee)))
|
|
|
|
(define (calculate-struct-size-and-offsets members)
|
|
(let* ((size 0)
|
|
(largest-member-size 0)
|
|
(offsets (map (lambda (member)
|
|
(let* ((name (cdr member))
|
|
(type (car member))
|
|
(type-alignment (pffi-align-of type)))
|
|
(when (> (pffi-size-of type) largest-member-size)
|
|
(set! largest-member-size (pffi-size-of type)))
|
|
(if (or (= size 0)
|
|
(= (floor-remainder size type-alignment) 0))
|
|
(begin
|
|
(set! size (+ size type-alignment))
|
|
(list name type (- size type-alignment)))
|
|
(let ((next-alignment (round-to-next-modulo-of size type-alignment)))
|
|
(set! size (+ next-alignment type-alignment))
|
|
(list name
|
|
type
|
|
next-alignment)))))
|
|
members)))
|
|
(list (cons 'size
|
|
(cond-expand
|
|
;(guile (sizeof (map pffi-type->native-type (map car members))))
|
|
(else
|
|
(if (= (modulo size largest-member-size) 0)
|
|
size
|
|
(round-to-next-modulo-of size largest-member-size)))))
|
|
(cons 'offsets offsets))))
|
|
|
|
(define pffi-struct-make
|
|
(lambda (name members . pointer)
|
|
(for-each
|
|
(lambda (member)
|
|
(when (not (pair? member))
|
|
(error "All struct members must be pairs" (list name member)))
|
|
(when (not (symbol? (car member)))
|
|
(error "All struct member types must be symbols" (list name member)))
|
|
(when (not (symbol? (cdr member)))
|
|
(error "All struct member names must be symbols" (list name member))))
|
|
members)
|
|
(let* ((size-and-offsets (calculate-struct-size-and-offsets members))
|
|
(size (cdr (assoc 'size size-and-offsets)))
|
|
(offsets (cdr (assoc 'offsets size-and-offsets)))
|
|
(pointer (if (null? pointer) (pffi-pointer-allocate size) (car pointer)))
|
|
(name (if (string? name) name (symbol->string name))))
|
|
(struct-make name size pointer offsets))))
|
|
|
|
(define (pffi-struct-offset-get struct member-name)
|
|
(when (not (assoc member-name (pffi-struct-members struct)))
|
|
(error "Struct has no such member" (list struct member-name)))
|
|
(car (cdr (cdr (assoc member-name (pffi-struct-members struct))))))
|
|
|
|
(define (pffi-struct-get struct member-name)
|
|
(when (not (assoc member-name (pffi-struct-members struct)))
|
|
(error "Struct has no such member" (list struct member-name)))
|
|
(let ((type (car (cdr (assoc member-name (pffi-struct-members struct)))))
|
|
(offset (car (cdr (cdr (assoc member-name (pffi-struct-members struct)))))))
|
|
(map display (list "type: " type
|
|
", offset: " offset
|
|
", value: " (pffi-pointer-get (pffi-struct-pointer struct) type offset)
|
|
#\newline))
|
|
(pffi-pointer-get (pffi-struct-pointer struct) type offset)))
|
|
|
|
(define (pffi-struct-set! struct member-name value)
|
|
(when (not (assoc member-name (pffi-struct-members struct)))
|
|
(error "Struct has no such member" (list struct member-name)))
|
|
(let ((type (car (cdr (assoc member-name (pffi-struct-members struct)))))
|
|
(offset (car (cdr (cdr (assoc member-name (pffi-struct-members struct)))))))
|
|
(pffi-pointer-set! (pffi-struct-pointer struct) type offset value)))
|