123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- #!/bin/sh
- exec guile -q -s "$0" "$@"
- !#
- ;;; test-ffi --- Foreign function interface. -*- Scheme -*-
- ;;;
- ;;; Copyright (C) 2010 Free Software Foundation, Inc.
- ;;;
- ;;; This library is free software; you can redistribute it and/or
- ;;; modify it under the terms of the GNU Lesser General Public
- ;;; License as published by the Free Software Foundation; either
- ;;; version 3 of the License, or (at your option) any later version.
- ;;;
- ;;; This library is distributed in the hope that it will be useful,
- ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ;;; Lesser General Public License for more details.
- ;;;
- ;;; You should have received a copy of the GNU Lesser General Public
- ;;; License along with this library; if not, write to the Free Software
- ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- (use-modules (system foreign)
- (rnrs bytevectors)
- (srfi srfi-1)
- (srfi srfi-26))
- (define lib
- (dynamic-link (string-append (getenv "builddir") "/libtest-ffi")))
- (define failed? #f)
- (define-syntax test
- (syntax-rules ()
- ((_ exp res)
- (let ((expected res)
- (actual exp))
- (if (not (equal? actual expected))
- (begin
- (set! failed? #t)
- (format (current-error-port)
- "bad return from expression `~a': expected ~A; got ~A~%"
- 'exp expected actual)))))))
- ;;;
- ;;; No args
- ;;;
- (define f-v-
- (pointer->procedure void (dynamic-func "test_ffi_v_" lib) '()))
- (test (f-v-) *unspecified*)
- (define f-s8-
- (pointer->procedure int8 (dynamic-func "test_ffi_s8_" lib) '()))
- (test (f-s8-) -100)
- (define f-u8-
- (pointer->procedure uint8 (dynamic-func "test_ffi_u8_" lib) '()))
- (test (f-u8-) 200)
- (define f-s16-
- (pointer->procedure int16 (dynamic-func "test_ffi_s16_" lib) '()))
- (test (f-s16-) -20000)
- (define f-u16-
- (pointer->procedure uint16 (dynamic-func "test_ffi_u16_" lib) '()))
- (test (f-u16-) 40000)
- (define f-s32-
- (pointer->procedure int32 (dynamic-func "test_ffi_s32_" lib) '()))
- (test (f-s32-) -2000000000)
- (define f-u32-
- (pointer->procedure uint32 (dynamic-func "test_ffi_u32_" lib) '()))
- (test (f-u32-) 4000000000)
- (define f-s64-
- (pointer->procedure int64 (dynamic-func "test_ffi_s64_" lib) '()))
- (test (f-s64-) -2000000000)
- (define f-u64-
- (pointer->procedure uint64 (dynamic-func "test_ffi_u64_" lib) '()))
- (test (f-u64-) 4000000000)
- ;;;
- ;;; One u8 arg
- ;;;
- (define f-v-u8
- (pointer->procedure void (dynamic-func "test_ffi_v_u8" lib) (list uint8)))
- (test (f-v-u8 10) *unspecified*)
- (define f-s8-u8
- (pointer->procedure int8 (dynamic-func "test_ffi_s8_u8" lib) (list uint8)))
- (test (f-s8-u8 10) -90)
- (define f-u8-u8
- (pointer->procedure uint8 (dynamic-func "test_ffi_u8_u8" lib) (list uint8)))
- (test (f-u8-u8 10) 210)
- (define f-s16-u8
- (pointer->procedure int16 (dynamic-func "test_ffi_s16_u8" lib) (list uint8)))
- (test (f-s16-u8 10) -19990)
- (define f-u16-u8
- (pointer->procedure uint16 (dynamic-func "test_ffi_u16_u8" lib) (list uint8)))
- (test (f-u16-u8 10) 40010)
- (define f-s32-u8
- (pointer->procedure int32 (dynamic-func "test_ffi_s32_u8" lib) (list uint8)))
- (test (f-s32-u8 10) -1999999990)
- (define f-u32-u8
- (pointer->procedure uint32 (dynamic-func "test_ffi_u32_u8" lib) (list uint8)))
- (test (f-u32-u8 10) 4000000010)
- (define f-s64-u8
- (pointer->procedure int64 (dynamic-func "test_ffi_s64_u8" lib) (list uint8)))
- (test (f-s64-u8 10) -1999999990)
- (define f-u64-u8
- (pointer->procedure uint64 (dynamic-func "test_ffi_u64_u8" lib) (list uint8)))
- (test (f-u64-u8 10) 4000000010)
- ;;;
- ;;; One s64 arg
- ;;;
- (define f-v-s64
- (pointer->procedure void (dynamic-func "test_ffi_v_s64" lib) (list int64)))
- (test (f-v-s64 10) *unspecified*)
- (define f-s8-s64
- (pointer->procedure int8 (dynamic-func "test_ffi_s8_s64" lib) (list int64)))
- (test (f-s8-s64 10) -90)
- (define f-u8-s64
- (pointer->procedure uint8 (dynamic-func "test_ffi_u8_s64" lib) (list int64)))
- (test (f-u8-s64 10) 210)
- (define f-s16-s64
- (pointer->procedure int16 (dynamic-func "test_ffi_s16_s64" lib) (list int64)))
- (test (f-s16-s64 10) -19990)
- (define f-u16-s64
- (pointer->procedure uint16 (dynamic-func "test_ffi_u16_s64" lib) (list int64)))
- (test (f-u16-s64 10) 40010)
- (define f-s32-s64
- (pointer->procedure int32 (dynamic-func "test_ffi_s32_s64" lib) (list int64)))
- (test (f-s32-s64 10) -1999999990)
- (define f-u32-s64
- (pointer->procedure uint32 (dynamic-func "test_ffi_u32_s64" lib) (list int64)))
- (test (f-u32-s64 10) 4000000010)
- (define f-s64-s64
- (pointer->procedure int64 (dynamic-func "test_ffi_s64_s64" lib) (list int64)))
- (test (f-s64-s64 10) -1999999990)
- (define f-u64-s64
- (pointer->procedure uint64 (dynamic-func "test_ffi_u64_s64" lib) (list int64)))
- (test (f-u64-s64 10) 4000000010)
- ;;
- ;; Multiple int args of differing types
- ;;
- (define f-sum
- (pointer->procedure int64 (dynamic-func "test_ffi_sum" lib)
- (list int8 int16 int32 int64)))
- (test (f-sum -1 2000 -30000 40000000000)
- (+ -1 2000 -30000 40000000000))
- ;;
- ;; More than ten arguments
- ;;
- (define f-sum-many
- (pointer->procedure int64 (dynamic-func "test_ffi_sum_many" lib)
- (list uint8 uint16 uint32 uint64
- int8 int16 int32 int64
- int8 int16 int32 int64)))
- (test (f-sum-many 255 65535 4294967295 1844674407370955161
- -1 2000 -30000 40000000000
- 5 -6000 70000 -80000000000)
- (+ 255 65535 4294967295 1844674407370955161
- -1 2000 -30000 40000000000
- 5 -6000 70000 -80000000000))
- ;;
- ;; Structs
- ;;
- (define f-sum-struct
- (pointer->procedure int64 (dynamic-func "test_ffi_sum_struct" lib)
- (list (list int8 int16 int32 int64))))
- (test (f-sum-struct (make-c-struct (list int8 int16 int32 int64)
- (list -1 2000 -30000 40000000000)))
- (+ -1 2000 -30000 40000000000))
- ;;
- ;; Structs
- ;;
- (define f-memcpy
- (pointer->procedure '* (dynamic-func "test_ffi_memcpy" lib)
- (list '* '* int32)))
- (let* ((src* '(0 1 2 3 4 5 6 7))
- (src (bytevector->pointer (u8-list->bytevector src*)))
- (dest (bytevector->pointer (make-bytevector 16 0)))
- (res (f-memcpy dest src (length src*))))
- (or (= (pointer-address dest) (pointer-address res))
- (error "memcpy res not equal to dest"))
- (or (equal? (bytevector->u8-list (pointer->bytevector dest 16))
- '(0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0))
- (error "unexpected dest")))
- ;;
- ;; Function pointers
- ;;
- (define f-callback-1
- (pointer->procedure int (dynamic-func "test_ffi_callback_1" lib)
- (list '* int)))
- (if (defined? 'procedure->pointer)
- (let* ((calls 0)
- (ptr (procedure->pointer int
- (lambda (x)
- (set! calls (+ 1 calls))
- (* x 3))
- (list int)))
- (input (iota 123)))
- (define (expected-result x)
- (+ 7 (* x 3)))
- (let ((result (map (cut f-callback-1 ptr <>) input)))
- (and (or (= calls (length input))
- (error "incorrect number of callback calls" calls))
- (or (equal? (map expected-result input) result)
- (error "incorrect result" result))))))
- (define f-callback-2
- (pointer->procedure double (dynamic-func "test_ffi_callback_2" lib)
- (list '* float int double)))
- (if (defined? 'procedure->pointer)
- (let* ((proc (lambda (x y z)
- (* (+ x (exact->inexact y)) z)))
- (ptr (procedure->pointer double proc
- (list float int double)))
- (arg1 (map (cut * <> 1.25) (iota 123 500)))
- (arg2 (iota 123))
- (arg3 (map (cut / <> 2.0) (iota 123 0 -10))))
- (define result
- (map (cut f-callback-2 ptr <> <> <>)
- arg1 arg2 arg3))
- (or (equal? result (map proc arg1 arg2 arg3))
- (error "incorrect result" result))))
- ;;;
- ;;; Global symbols.
- ;;;
- (use-modules ((rnrs bytevectors) #:select (utf8->string)))
- (if (defined? 'setlocale)
- (setlocale LC_ALL "C"))
- (define global (dynamic-link))
- (define strerror
- (pointer->procedure '* (dynamic-func "strerror" global)
- (list int)))
- (define strlen
- (pointer->procedure size_t (dynamic-func "strlen" global)
- (list '*)))
- (let* ((ptr (strerror ENOENT))
- (len (strlen ptr))
- (bv (pointer->bytevector ptr len 0 'u8))
- (str (utf8->string bv)))
- (test #t (not (not (string-contains str "file")))))
- (exit (not failed?))
- ;; Local Variables:
- ;; mode: scheme
- ;; End:
|