2 exec guile
-q -s "$0" "$@"
4 ;;; test-ffi
--- Foreign
function interface.
-*- Scheme
-*-
6 ;;; Copyright
(C
) 2010 Free Software Foundation
, Inc.
8 ;;; This library is free software
; you can redistribute it and
/or
9 ;;; modify it under the terms of the GNU Lesser General Public
10 ;;; License as published by the Free Software Foundation
; either
11 ;;; version
3 of the License
, or
(at your option
) any later version.
13 ;;; This library is distributed
in the hope that it will be useful
,
14 ;;; but WITHOUT ANY WARRANTY
; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ;;; Lesser General Public License
for more details.
18 ;;; You should have received a copy of the GNU Lesser General Public
19 ;;; License along with this library
; if not
, write to the Free Software
20 ;;; Foundation
, Inc.
, 51 Franklin Street
, Fifth Floor
, Boston
, MA
02110-1301 USA
22 (use-modules
(system foreign
)
28 (dynamic-link
(string-append
(getenv
"builddir") "/libtest-ffi")))
37 (if (not
(equal? actual expected
))
40 (format
(current-error-port
)
41 "bad return from expression `~a': expected ~A; got ~A~%"
42 'exp expected actual)))))))
48 (pointer->procedure void (dynamic-func "test_ffi_v_" lib) '()))
49 (test (f-v-
) *unspecified
*)
52 (pointer-
>procedure int8
(dynamic-func
"test_ffi_s8_" lib
) '()))
56 (pointer->procedure uint8 (dynamic-func "test_ffi_u8_" lib) '()))
60 (pointer-
>procedure int16
(dynamic-func
"test_ffi_s16_" lib
) '()))
61 (test (f-s16-) -20000)
64 (pointer->procedure uint16 (dynamic-func "test_ffi_u16_" lib) '()))
68 (pointer-
>procedure int32
(dynamic-func
"test_ffi_s32_" lib
) '()))
69 (test (f-s32-) -2000000000)
72 (pointer->procedure uint32 (dynamic-func "test_ffi_u32_" lib) '()))
73 (test (f-u32-
) 4000000000)
76 (pointer-
>procedure int64
(dynamic-func
"test_ffi_s64_" lib
) '()))
77 (test (f-s64-) -2000000000)
80 (pointer->procedure uint64 (dynamic-func "test_ffi_u64_" lib) '()))
81 (test (f-u64-
) 4000000000)
87 (pointer-
>procedure void
(dynamic-func
"test_ffi_v_u8" lib
) (list uint8
)))
88 (test (f-v-u8
10) *unspecified
*)
91 (pointer-
>procedure int8
(dynamic-func
"test_ffi_s8_u8" lib
) (list uint8
)))
92 (test (f-s8-u8
10) -90)
95 (pointer-
>procedure uint8
(dynamic-func
"test_ffi_u8_u8" lib
) (list uint8
)))
96 (test (f-u8-u8
10) 210)
99 (pointer-
>procedure int16
(dynamic-func
"test_ffi_s16_u8" lib
) (list uint8
)))
100 (test (f-s16-u8
10) -19990)
103 (pointer-
>procedure uint16
(dynamic-func
"test_ffi_u16_u8" lib
) (list uint8
)))
104 (test (f-u16-u8
10) 40010)
107 (pointer-
>procedure int32
(dynamic-func
"test_ffi_s32_u8" lib
) (list uint8
)))
108 (test (f-s32-u8
10) -1999999990)
111 (pointer-
>procedure uint32
(dynamic-func
"test_ffi_u32_u8" lib
) (list uint8
)))
112 (test (f-u32-u8
10) 4000000010)
115 (pointer-
>procedure int64
(dynamic-func
"test_ffi_s64_u8" lib
) (list uint8
)))
116 (test (f-s64-u8
10) -1999999990)
119 (pointer-
>procedure uint64
(dynamic-func
"test_ffi_u64_u8" lib
) (list uint8
)))
120 (test (f-u64-u8
10) 4000000010)
127 (pointer-
>procedure void
(dynamic-func
"test_ffi_v_s64" lib
) (list int64
)))
128 (test (f-v-s64
10) *unspecified
*)
131 (pointer-
>procedure int8
(dynamic-func
"test_ffi_s8_s64" lib
) (list int64
)))
132 (test (f-s8-s64
10) -90)
135 (pointer-
>procedure uint8
(dynamic-func
"test_ffi_u8_s64" lib
) (list int64
)))
136 (test (f-u8-s64
10) 210)
139 (pointer-
>procedure int16
(dynamic-func
"test_ffi_s16_s64" lib
) (list int64
)))
140 (test (f-s16-s64
10) -19990)
143 (pointer-
>procedure uint16
(dynamic-func
"test_ffi_u16_s64" lib
) (list int64
)))
144 (test (f-u16-s64
10) 40010)
147 (pointer-
>procedure int32
(dynamic-func
"test_ffi_s32_s64" lib
) (list int64
)))
148 (test (f-s32-s64
10) -1999999990)
151 (pointer-
>procedure uint32
(dynamic-func
"test_ffi_u32_s64" lib
) (list int64
)))
152 (test (f-u32-s64
10) 4000000010)
155 (pointer-
>procedure int64
(dynamic-func
"test_ffi_s64_s64" lib
) (list int64
)))
156 (test (f-s64-s64
10) -1999999990)
159 (pointer-
>procedure uint64
(dynamic-func
"test_ffi_u64_s64" lib
) (list int64
)))
160 (test (f-u64-s64
10) 4000000010)
164 ;; Multiple int args of differing types
167 (pointer-
>procedure int64
(dynamic-func
"test_ffi_sum" lib
)
168 (list int8 int16 int32 int64
)))
169 (test (f-sum
-1 2000 -30000 40000000000)
170 (+ -1 2000 -30000 40000000000))
173 ;; More than ten arguments
176 (pointer-
>procedure int64
(dynamic-func
"test_ffi_sum_many" lib
)
177 (list uint8 uint16 uint32 uint64
178 int8 int16 int32 int64
179 int8 int16 int32 int64
)))
180 (test (f-sum-many
255 65535 4294967295 1844674407370955161
181 -1 2000 -30000 40000000000
182 5 -6000 70000 -80000000000)
183 (+ 255 65535 4294967295 1844674407370955161
184 -1 2000 -30000 40000000000
185 5 -6000 70000 -80000000000))
191 (pointer-
>procedure int64
(dynamic-func
"test_ffi_sum_struct" lib
)
192 (list
(list int8 int16 int32 int64
))))
193 (test (f-sum-struct
(make-c-struct
(list int8 int16 int32 int64
)
194 (list
-1 2000 -30000 40000000000)))
195 (+ -1 2000 -30000 40000000000))
200 (pointer-
>procedure
'* (dynamic-func "test_ffi_memcpy" lib)
202 (let* ((src* '(0 1 2 3 4 5 6 7))
203 (src
(bytevector-
>pointer
(u8-list-
>bytevector src
*)))
204 (dest
(bytevector-
>pointer
(make-bytevector
16 0)))
205 (res
(f-memcpy dest src
(length src
*))))
206 (or
(= (pointer-address dest
) (pointer-address res
))
207 (error
"memcpy res not equal to dest"))
208 (or
(equal?
(bytevector-
>u8-list
(pointer-
>bytevector dest
16))
209 '(0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0))
210 (error "unexpected dest")))
217 (pointer->procedure int (dynamic-func "test_ffi_callback_1" lib)
220 (if (defined?
'procedure->pointer)
222 (ptr (procedure->pointer int
224 (set! calls (+ 1 calls))
228 (define (expected-result x)
231 (let ((result (map (cut f-callback-1 ptr <>) input)))
232 (and (or (= calls (length input))
233 (error "incorrect number of callback calls" calls))
234 (or (equal? (map expected-result input) result)
235 (error "incorrect result" result))))))
238 (pointer->procedure double (dynamic-func "test_ffi_callback_2" lib)
239 (list '* float int double
)))
241 (if (defined?
'procedure->pointer)
242 (let* ((proc (lambda (x y z)
243 (* (+ x (exact->inexact y)) z)))
244 (ptr (procedure->pointer double proc
245 (list float int double)))
246 (arg1 (map (cut * <> 1.25) (iota 123 500)))
248 (arg3 (map (cut / <> 2.0) (iota 123 0 -10))))
250 (map (cut f-callback-2 ptr <> <> <>)
253 (or (equal? result (map proc arg1 arg2 arg3))
254 (error "incorrect result" result))))
261 (use-modules ((rnrs bytevectors) #:select (utf8->string)))
263 (if (defined? 'setlocale
)
264 (setlocale LC_ALL
"C"))
266 (define global
(dynamic-link
))
269 (pointer-
>procedure
'* (dynamic-func "strerror" global)
273 (pointer->procedure size_t (dynamic-func "strlen" global)
276 (let* ((ptr
(strerror ENOENT
))
278 (bv
(pointer-
>bytevector ptr len
0 'u8))
279 (str (utf8->string bv)))
280 (test #t (not (not (string-contains str "file")))))