Add `string->pointer' and `pointer->string' to the FFI.
[bpt/guile.git] / module / system / foreign.scm
CommitLineData
ab4779ff
AW
1;;;; Copyright (C) 2010 Free Software Foundation, Inc.
2;;;;
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.
7;;;;
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.
12;;;;
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
16;;;;
17\f
18
19(define-module (system foreign)
07d22c02 20 #:use-module (rnrs bytevectors)
7387c231 21 #:use-module (srfi srfi-1)
ab4779ff
AW
22 #:export (void
23 float double
dd1464bf 24 int unsigned-int long unsigned-long size_t
ab4779ff
AW
25 int8 uint8
26 uint16 int16
27 uint32 int32
28 uint64 int64
29
70ea39f7
AW
30 sizeof alignof
31
d4149a51
LC
32 %null-pointer
33 null-pointer?
34 make-pointer
5b46a8c2 35 pointer-address
d4149a51 36
5b46a8c2
LC
37 pointer->bytevector
38 bytevector->pointer
39 set-pointer-finalizer!
40
fa2a89a6
LC
41 dereference-pointer
42 string->pointer
43 pointer->string
44
70ea39f7
AW
45 make-foreign-function
46 make-c-struct parse-c-struct))
ab4779ff 47
44602b08
AW
48(load-extension (string-append "libguile-" (effective-version))
49 "scm_init_foreign")
70ea39f7 50
d4149a51
LC
51\f
52;;;
53;;; Pointers.
54;;;
55
56(define (null-pointer? pointer)
183a2a22 57 "Return true if POINTER is the null pointer."
5b46a8c2 58 (= (pointer-address pointer) 0))
d4149a51
LC
59
60
61\f
62;;;
63;;; Structures.
64;;;
65
70ea39f7
AW
66(define *writers*
67 `((,float . ,bytevector-ieee-single-native-set!)
68 (,double . ,bytevector-ieee-double-native-set!)
69 (,int8 . ,bytevector-s8-set!)
70 (,uint8 . ,bytevector-u8-set!)
71 (,int16 . ,bytevector-s16-native-set!)
72 (,uint16 . ,bytevector-u16-native-set!)
73 (,int32 . ,bytevector-s32-native-set!)
74 (,uint32 . ,bytevector-u32-native-set!)
75 (,int64 . ,bytevector-s64-native-set!)
76 (,uint64 . ,bytevector-u64-native-set!)))
77
78(define *readers*
79 `((,float . ,bytevector-ieee-single-native-ref)
80 (,double . ,bytevector-ieee-double-native-ref)
81 (,int8 . ,bytevector-s8-ref)
82 (,uint8 . ,bytevector-u8-ref)
83 (,int16 . ,bytevector-s16-native-ref)
84 (,uint16 . ,bytevector-u16-native-ref)
85 (,int32 . ,bytevector-s32-native-ref)
86 (,uint32 . ,bytevector-u32-native-ref)
87 (,int64 . ,bytevector-s64-native-ref)
88 (,uint64 . ,bytevector-u64-native-ref)))
89
90(define (align off alignment)
91 (1+ (logior (1- off) (1- alignment))))
92
93(define (write-c-struct bv offset types vals)
94 (let lp ((offset offset) (types types) (vals vals))
95 (cond
96 ((not (pair? types))
97 (or (null? vals)
98 (error "too many values" vals)))
99 ((not (pair? vals))
100 (error "too few values" types))
101 (else
102 ;; alignof will error-check
103 (let* ((type (car types))
104 (offset (align offset (alignof type))))
105 (if (pair? type)
106 (write-c-struct bv offset (car types) (car vals))
107 ((assv-ref *writers* type) bv offset (car vals)))
108 (lp (+ offset (sizeof type)) (cdr types) (cdr vals)))))))
109
110(define (read-c-struct bv offset types)
111 (let lp ((offset offset) (types types) (vals '()))
112 (cond
113 ((not (pair? types))
114 (reverse vals))
115 (else
116 ;; alignof will error-check
117 (let* ((type (car types))
118 (offset (align offset (alignof type))))
119 (lp (+ offset (sizeof type)) (cdr types)
120 (cons (if (pair? type)
121 (read-c-struct bv offset (car types))
122 ((assv-ref *readers* type) bv offset))
123 vals)))))))
124
125(define (make-c-struct types vals)
126 (let ((bv (make-bytevector (sizeof types) 0)))
127 (write-c-struct bv 0 types vals)
5b46a8c2 128 (bytevector->pointer bv)))
70ea39f7
AW
129
130(define (parse-c-struct foreign types)
7387c231
LC
131 (let ((size (fold (lambda (type total)
132 (+ (sizeof type) total))
133 0
134 types)))
135 (read-c-struct (pointer->bytevector foreign size) 0 types)))