1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-28 14:00:31 +02:00
guile/test-suite/standalone/test-ffi
Ludovic Courtès 760538bf75 Add license header to `test-ffi'.
* test-suite/standalone/test-ffi: Add license header.
2010-09-03 15:32:31 +02:00

271 lines
8.2 KiB
Scheme
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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-
(make-foreign-function void (dynamic-func "test_ffi_v_" lib) '()))
(test (f-v-) *unspecified*)
(define f-s8-
(make-foreign-function int8 (dynamic-func "test_ffi_s8_" lib) '()))
(test (f-s8-) -100)
(define f-u8-
(make-foreign-function uint8 (dynamic-func "test_ffi_u8_" lib) '()))
(test (f-u8-) 200)
(define f-s16-
(make-foreign-function int16 (dynamic-func "test_ffi_s16_" lib) '()))
(test (f-s16-) -20000)
(define f-u16-
(make-foreign-function uint16 (dynamic-func "test_ffi_u16_" lib) '()))
(test (f-u16-) 40000)
(define f-s32-
(make-foreign-function int32 (dynamic-func "test_ffi_s32_" lib) '()))
(test (f-s32-) -2000000000)
(define f-u32-
(make-foreign-function uint32 (dynamic-func "test_ffi_u32_" lib) '()))
(test (f-u32-) 4000000000)
(define f-s64-
(make-foreign-function int64 (dynamic-func "test_ffi_s64_" lib) '()))
(test (f-s64-) -2000000000)
(define f-u64-
(make-foreign-function uint64 (dynamic-func "test_ffi_u64_" lib) '()))
(test (f-u64-) 4000000000)
;;;
;;; One u8 arg
;;;
(define f-v-u8
(make-foreign-function void (dynamic-func "test_ffi_v_u8" lib) (list uint8)))
(test (f-v-u8 10) *unspecified*)
(define f-s8-u8
(make-foreign-function int8 (dynamic-func "test_ffi_s8_u8" lib) (list uint8)))
(test (f-s8-u8 10) -90)
(define f-u8-u8
(make-foreign-function uint8 (dynamic-func "test_ffi_u8_u8" lib) (list uint8)))
(test (f-u8-u8 10) 210)
(define f-s16-u8
(make-foreign-function int16 (dynamic-func "test_ffi_s16_u8" lib) (list uint8)))
(test (f-s16-u8 10) -19990)
(define f-u16-u8
(make-foreign-function uint16 (dynamic-func "test_ffi_u16_u8" lib) (list uint8)))
(test (f-u16-u8 10) 40010)
(define f-s32-u8
(make-foreign-function int32 (dynamic-func "test_ffi_s32_u8" lib) (list uint8)))
(test (f-s32-u8 10) -1999999990)
(define f-u32-u8
(make-foreign-function uint32 (dynamic-func "test_ffi_u32_u8" lib) (list uint8)))
(test (f-u32-u8 10) 4000000010)
(define f-s64-u8
(make-foreign-function int64 (dynamic-func "test_ffi_s64_u8" lib) (list uint8)))
(test (f-s64-u8 10) -1999999990)
(define f-u64-u8
(make-foreign-function uint64 (dynamic-func "test_ffi_u64_u8" lib) (list uint8)))
(test (f-u64-u8 10) 4000000010)
;;;
;;; One s64 arg
;;;
(define f-v-s64
(make-foreign-function void (dynamic-func "test_ffi_v_s64" lib) (list int64)))
(test (f-v-s64 10) *unspecified*)
(define f-s8-s64
(make-foreign-function int8 (dynamic-func "test_ffi_s8_s64" lib) (list int64)))
(test (f-s8-s64 10) -90)
(define f-u8-s64
(make-foreign-function uint8 (dynamic-func "test_ffi_u8_s64" lib) (list int64)))
(test (f-u8-s64 10) 210)
(define f-s16-s64
(make-foreign-function int16 (dynamic-func "test_ffi_s16_s64" lib) (list int64)))
(test (f-s16-s64 10) -19990)
(define f-u16-s64
(make-foreign-function uint16 (dynamic-func "test_ffi_u16_s64" lib) (list int64)))
(test (f-u16-s64 10) 40010)
(define f-s32-s64
(make-foreign-function int32 (dynamic-func "test_ffi_s32_s64" lib) (list int64)))
(test (f-s32-s64 10) -1999999990)
(define f-u32-s64
(make-foreign-function uint32 (dynamic-func "test_ffi_u32_s64" lib) (list int64)))
(test (f-u32-s64 10) 4000000010)
(define f-s64-s64
(make-foreign-function int64 (dynamic-func "test_ffi_s64_s64" lib) (list int64)))
(test (f-s64-s64 10) -1999999990)
(define f-u64-s64
(make-foreign-function 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
(make-foreign-function int64 (dynamic-func "test_ffi_sum" lib)
(list int8 int16 int32 int64)))
(test (f-sum -1 2000 -30000 40000000000)
(+ -1 2000 -30000 40000000000))
;;
;; Structs
;;
(define f-sum-struct
(make-foreign-function 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
(make-foreign-function '* (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
(make-foreign-function 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
(make-foreign-function 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
(make-foreign-function '* (dynamic-func "strerror" global)
(list int)))
(define strlen
(make-foreign-function 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: