1 ;;;; Copyright (C) 2010 Free Software Foundation, Inc.
3 ;;;; This library is free software; you can redistribute it and/or
4 ;;;; modify it under the terms of the GNU Lesser General Public
5 ;;;; License as published by the Free Software Foundation; either
6 ;;;; version 2.1 of the License, or (at your option) any later version.
8 ;;;; This library is distributed in the hope that it will be useful,
9 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 ;;;; Lesser General Public License for more details.
13 ;;;; You should have received a copy of the GNU Lesser General Public
14 ;;;; License along with this library; if not, write to the Free Software
15 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (define-module (system foreign)
20 #:use-module (rnrs bytevectors)
21 #:use-module (srfi srfi-1)
26 int unsigned-int long unsigned-long size_t
41 set-pointer-finalizer!
48 ;; procedure->pointer (see below)
49 make-c-struct parse-c-struct))
51 (eval-when (load eval compile)
52 (load-extension (string-append "libguile-" (effective-version))
60 (define (null-pointer? pointer)
61 "Return true if POINTER is the null pointer."
62 (= (pointer-address pointer) 0))
64 (if (defined? 'procedure->pointer)
65 (export procedure->pointer))
72 (define-syntax compile-time-value
74 "Evaluate the given expression at compile time. The expression must
75 evaluate to a simple datum."
77 (let-syntax ((v (lambda (s)
80 (_ (datum->syntax s val)))))))
83 (eval-when (eval compile load)
84 ;; The procedures below are used at compile time by the macros below.
86 (define (integer-ref type signed?)
89 'bytevector-s64-native-ref
90 'bytevector-u64-native-ref))
92 'bytevector-s32-native-ref
93 'bytevector-u32-native-ref))
95 'bytevector-s16-native-ref
96 'bytevector-u16-native-ref))
98 (error "what machine is this?" type (sizeof type)))))
100 (define (integer-set type signed?)
103 'bytevector-s64-native-set!
104 'bytevector-u64-native-set!))
106 'bytevector-s32-native-set!
107 'bytevector-u32-native-set!))
109 'bytevector-s16-native-set!
110 'bytevector-u16-native-set!))
112 (error "what machine is this?" type (sizeof type))))))
114 (define-syntax define-integer-reader
116 ((_ name type signed?)
117 (letrec-syntax ((ref (identifier-syntax
119 (integer-ref type signed?)))))
120 (define name ref)))))
122 (define-syntax define-integer-writer
124 ((_ name type signed?)
125 (letrec-syntax ((set (identifier-syntax
127 (integer-set type signed?)))))
128 (define name set)))))
131 (define-integer-reader %read-short short #t)
132 (define-integer-reader %read-int int #t)
133 (define-integer-reader %read-long long #t)
134 (define-integer-writer %write-short! short #t)
135 (define-integer-writer %write-int! int #t)
136 (define-integer-writer %write-long! long #t)
138 (define-integer-reader %read-unsigned-short unsigned-short #f)
139 (define-integer-reader %read-unsigned-int unsigned-int #f)
140 (define-integer-reader %read-unsigned-long unsigned-long #f)
141 (define-integer-writer %write-unsigned-short! unsigned-short #f)
142 (define-integer-writer %write-unsigned-int! unsigned-int #f)
143 (define-integer-writer %write-unsigned-long! unsigned-long #f)
145 (define-integer-reader %read-size_t size_t #f)
146 (define-integer-writer %write-size_t! size_t #f)
148 (define-integer-reader %read-pointer '* #f)
149 (define-integer-writer %write-pointer! '* #f)
153 `((,float . ,bytevector-ieee-single-native-set!)
154 (,double . ,bytevector-ieee-double-native-set!)
155 (,int8 . ,bytevector-s8-set!)
156 (,uint8 . ,bytevector-u8-set!)
157 (,int16 . ,bytevector-s16-native-set!)
158 (,uint16 . ,bytevector-u16-native-set!)
159 (,int32 . ,bytevector-s32-native-set!)
160 (,uint32 . ,bytevector-u32-native-set!)
161 (,int64 . ,bytevector-s64-native-set!)
162 (,uint64 . ,bytevector-u64-native-set!)
164 (,short . ,%write-short!)
165 (,unsigned-short . ,%write-unsigned-short!)
166 (,int . ,%write-int!)
167 (,unsigned-int . ,%write-unsigned-int!)
168 (,long . ,%write-long!)
169 (,unsigned-long . ,%write-unsigned-long!)
170 (,size_t . ,%write-size_t!)
172 (* . ,(lambda (bv offset ptr)
173 (%write-pointer! bv offset
174 (pointer-address ptr))))))
177 `((,float . ,bytevector-ieee-single-native-ref)
178 (,double . ,bytevector-ieee-double-native-ref)
179 (,int8 . ,bytevector-s8-ref)
180 (,uint8 . ,bytevector-u8-ref)
181 (,int16 . ,bytevector-s16-native-ref)
182 (,uint16 . ,bytevector-u16-native-ref)
183 (,int32 . ,bytevector-s32-native-ref)
184 (,uint32 . ,bytevector-u32-native-ref)
185 (,int64 . ,bytevector-s64-native-ref)
186 (,uint64 . ,bytevector-u64-native-ref)
188 (,short . ,%read-short)
189 (,unsigned-short . ,%read-unsigned-short)
191 (,unsigned-int . ,%read-unsigned-int)
192 (,long . ,%read-long)
193 (,unsigned-long . ,%read-unsigned-long)
194 (,size_t . ,%read-size_t)
196 (* . ,(lambda (bv offset)
197 (make-pointer (%read-pointer bv offset))))))
199 (define (align off alignment)
200 (1+ (logior (1- off) (1- alignment))))
202 (define (write-c-struct bv offset types vals)
203 (let lp ((offset offset) (types types) (vals vals))
207 (error "too many values" vals)))
209 (error "too few values" types))
211 ;; alignof will error-check
212 (let* ((type (car types))
213 (offset (align offset (alignof type))))
215 (write-c-struct bv offset (car types) (car vals))
216 ((assv-ref *writers* type) bv offset (car vals)))
217 (lp (+ offset (sizeof type)) (cdr types) (cdr vals)))))))
219 (define (read-c-struct bv offset types)
220 (let lp ((offset offset) (types types) (vals '()))
225 ;; alignof will error-check
226 (let* ((type (car types))
227 (offset (align offset (alignof type))))
228 (lp (+ offset (sizeof type)) (cdr types)
229 (cons (if (pair? type)
230 (read-c-struct bv offset (car types))
231 ((assv-ref *readers* type) bv offset))
234 (define (make-c-struct types vals)
235 (let ((bv (make-bytevector (sizeof types) 0)))
236 (write-c-struct bv 0 types vals)
237 (bytevector->pointer bv)))
239 (define (parse-c-struct foreign types)
240 (let ((size (fold (lambda (type total)
242 (align total (alignof type))))
245 (read-c-struct (pointer->bytevector foreign size) 0 types)))