Tmux etc
This commit is contained in:
parent
276853ba84
commit
1cb167b597
361 changed files with 77302 additions and 4 deletions
|
|
@ -0,0 +1,98 @@
|
|||
# -*- Mode: Makefile; tab-width: 3; indent-tabs-mode: t -*-
|
||||
#
|
||||
# Makefile --- Make targets for various tasks.
|
||||
#
|
||||
# Copyright (C) 2005, James Bielman <jamesjb@jamesjb.com>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use, copy,
|
||||
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
OSTYPE = $(shell uname)
|
||||
ARCH = $(shell uname -m)
|
||||
|
||||
CC := gcc
|
||||
CFLAGS := -Wall -std=c99 -pedantic
|
||||
SHLIB_CFLAGS := -shared
|
||||
SHLIB_EXT := .so
|
||||
|
||||
ifneq ($(if $(filter Linux %BSD,$(OSTYPE)),OK), OK)
|
||||
ifeq ($(OSTYPE), Darwin)
|
||||
SHLIB_CFLAGS := -dynamiclib
|
||||
SHLIB_EXT := .dylib
|
||||
ifeq ($(shell sysctl -n hw.optional.x86_64), 1)
|
||||
ARCH := x86_64
|
||||
CFLAGS_64 := -m64
|
||||
endif
|
||||
else
|
||||
ifeq ($(OSTYPE), SunOS)
|
||||
CFLAGS := -m64 -fPIC -c -Wall -std=c99 -pedantic
|
||||
else
|
||||
# Let's assume this is win32
|
||||
SHLIB_EXT := .dll
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(ARCH), x86_64)
|
||||
CFLAGS += -lm
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
CFLAGS_64 += -fPIC
|
||||
endif
|
||||
|
||||
# Are all G5s ppc970s?
|
||||
ifeq ($(ARCH), ppc970)
|
||||
CFLAGS_64 += -m64
|
||||
endif
|
||||
|
||||
SHLIBS = libtest$(SHLIB_EXT) libtest2$(SHLIB_EXT) libfsbv$(SHLIB_EXT)
|
||||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
SHLIBS += libtest32$(SHLIB_EXT) libtest2_32$(SHLIB_EXT) libfsbv_32$(SHLIB_EXT)
|
||||
endif
|
||||
|
||||
shlibs: $(SHLIBS)
|
||||
|
||||
libtest$(SHLIB_EXT): libtest.c
|
||||
$(CC) -o $@ $(SHLIB_CFLAGS) $(CFLAGS) $(CFLAGS_64) $<
|
||||
|
||||
libtest2$(SHLIB_EXT): libtest2.c
|
||||
$(CC) -o $@ $(SHLIB_CFLAGS) $(CFLAGS) $(CFLAGS_64) $<
|
||||
|
||||
libfsbv$(SHLIB_EXT): libfsbv.c
|
||||
$(CC) -o $@ $(SHLIB_CFLAGS) $(CFLAGS) $(CFLAGS_64) $<
|
||||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
libtest32$(SHLIB_EXT): libtest.c
|
||||
-$(CC) -m32 -o $@ $(SHLIB_CFLAGS) $(CFLAGS) $<
|
||||
|
||||
libtest2_32$(SHLIB_EXT): libtest2.c
|
||||
-$(CC) -m32 -o $@ $(SHLIB_CFLAGS) $(CFLAGS) $<
|
||||
|
||||
libfsbv_32$(SHLIB_EXT): libfsbv.c
|
||||
-$(CC) -m32 -o $@ $(SHLIB_CFLAGS) $(CFLAGS) $<
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f *.so *.dylib *.dll *.bundle
|
||||
|
||||
# vim: ft=make ts=3 noet
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
shlibs clean:
|
||||
gmake $@
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; arrays.lisp --- Tests for foreign arrays.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, James Bielman <jamesjb@jamesjb.com>
|
||||
;;; Copyright (C) 2005-2007, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
;;;#Foreign Array Conversion Tests
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(deftest array.foreign-to-lisp.basic
|
||||
(with-foreign-array (ptr #(1 2 3 4 5) '(:array :int32 5))
|
||||
(foreign-array-to-lisp ptr '(:array :int32 5)))
|
||||
#(1 2 3 4 5))
|
||||
|
||||
(deftest array.foreign-to-lisp.adjustable
|
||||
(with-foreign-array (ptr #(1 2 3 4 5) '(:array :int32 5))
|
||||
(let ((array (foreign-array-to-lisp ptr '(:array :int32 5)
|
||||
:adjustable t)))
|
||||
(adjustable-array-p array)))
|
||||
t)
|
||||
|
||||
(deftest array.foreign-to-lisp.displaced
|
||||
(let ((array (make-array 10 :initial-contents '(1 2 3 4 5 6 7 8 9 0))))
|
||||
(with-foreign-array (ptr #(10 20 30 40 50) '(:array :int32 5))
|
||||
(let ((displaced (foreign-array-to-lisp ptr '(:array :int32 5)
|
||||
:displaced-to array
|
||||
:displaced-index-offset 5)))
|
||||
array)))
|
||||
#(1 2 3 4 5 10 20 30 40 50))
|
||||
|
||||
;;; Implementation detail: 15.1.2.2 of the CL standard states that the only
|
||||
;;; truly portable array specializations are for bits (bit-vectors) and
|
||||
;;; characters (strings). Since char-codes are implementation-dependent, it
|
||||
;;; would be tricky to write a portable test for them without generating
|
||||
;;; characters at runtime. So, for a truly portable test, we are only left with
|
||||
;;; bits, which are luckily numeric, and equal to (UNSIGNED-BYTE 1).
|
||||
;;; This is why the below test is so terribly wasteful, spending a whole byte
|
||||
;;; for a single bit - CFFI has no capabilities for dealing with single bits,
|
||||
;;; and this test is only meant to check correctness of the :ELEMENT-TYPE
|
||||
;;; argument to MAKE-ARRAY. In actual use cases of specialized
|
||||
;;; FOREIGN-ARRAY-TO-LISP, capable implementations will be able to make
|
||||
;;; specialized arrays of types that are commonly optimized for and/or
|
||||
;;; representable in hardware, such as (UNSIGNED-BYTE 8) on x86 architectures.
|
||||
(deftest array.foreign-to-lisp.specialized
|
||||
(with-foreign-array (ptr #(1 0 1 0 1 1 1 0) '(:array :int8 8))
|
||||
(foreign-array-to-lisp ptr '(:array :int8 8) :element-type 'bit))
|
||||
#*10101110)
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; libtest.lisp --- Setup CFFI bindings for libtest.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2007, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(define-foreign-library (libtest :type :test)
|
||||
(:darwin (:or "libtest.dylib" "libtest32.dylib"))
|
||||
(:unix (:or "libtest.so" "libtest32.so"))
|
||||
(:windows "libtest.dll")
|
||||
(t (:default "libtest")))
|
||||
|
||||
(define-foreign-library (libtest2 :type :test)
|
||||
(:darwin (:or "libtest2.dylib" "libtest2_32.dylib"))
|
||||
(:unix (:or "libtest2.so" "libtest2_32.so"))
|
||||
(t (:default "libtest2")))
|
||||
|
||||
(define-foreign-library (libfsbv :type :test)
|
||||
(:darwin (:or "libfsbv.dylib" "libfsbv32.dylib"))
|
||||
(:unix (:or "libfsbv.so" "libfsbv_32.so"))
|
||||
(:windows "libfsbv.dll")
|
||||
(t (:default "libfsbv")))
|
||||
|
||||
(define-foreign-library libc
|
||||
(:windows "msvcrt.dll"))
|
||||
|
||||
(define-foreign-library libm
|
||||
#+(and lispworks darwin) ; not sure why the full path is necessary
|
||||
(:darwin "/usr/lib/libm.dylib")
|
||||
(t (:default "libm")))
|
||||
|
||||
(defmacro deftest (name &rest body)
|
||||
(destructuring-bind (name &key expected-to-fail)
|
||||
(alexandria:ensure-list name)
|
||||
(let ((result `(rt:deftest ,name ,@body)))
|
||||
(when expected-to-fail
|
||||
(setf result `(progn
|
||||
(when ,expected-to-fail
|
||||
(pushnew ',name rt::*expected-failures*))
|
||||
,result)))
|
||||
result)))
|
||||
|
||||
(defun call-within-new-thread (fn &rest args)
|
||||
(let (result
|
||||
error
|
||||
(cv (bordeaux-threads:make-condition-variable))
|
||||
(lock (bordeaux-threads:make-lock)))
|
||||
(bordeaux-threads:with-lock-held (lock)
|
||||
(bordeaux-threads:make-thread
|
||||
(lambda ()
|
||||
(multiple-value-setq (result error)
|
||||
(ignore-errors (apply fn args)))
|
||||
(bordeaux-threads:with-lock-held (lock)
|
||||
(bordeaux-threads:condition-notify cv))))
|
||||
(bordeaux-threads:condition-wait cv lock)
|
||||
(values result error))))
|
||||
|
||||
;;; As of OSX 10.6.6, loading CoreFoundation on something other than
|
||||
;;; the initial thread results in a crash.
|
||||
(deftest load-core-foundation
|
||||
(progn
|
||||
#+bordeaux-threads
|
||||
(call-within-new-thread 'load-foreign-library
|
||||
'(:framework "CoreFoundation"))
|
||||
t)
|
||||
t)
|
||||
|
||||
;;; Return the directory containing the source when compiling or
|
||||
;;; loading this file. We don't use *LOAD-TRUENAME* because the fasl
|
||||
;;; file may be in a different directory than the source with certain
|
||||
;;; ASDF extensions loaded.
|
||||
(defun load-directory ()
|
||||
(let ((here #.(or *compile-file-truename* *load-truename*)))
|
||||
(make-pathname :name nil :type nil :version nil
|
||||
:defaults here)))
|
||||
|
||||
(defun load-test-libraries ()
|
||||
(let ((*foreign-library-directories* (list (load-directory))))
|
||||
(load-foreign-library 'libtest)
|
||||
(load-foreign-library 'libtest2)
|
||||
(load-foreign-library 'libfsbv)
|
||||
(load-foreign-library 'libc)
|
||||
#+(or abcl lispworks) (load-foreign-library 'libm)))
|
||||
|
||||
#-(:and :ecl (:not :dffi))
|
||||
(load-test-libraries)
|
||||
|
||||
#+(:and :ecl (:not :dffi))
|
||||
(ffi:load-foreign-library
|
||||
#.(make-pathname :name "libtest" :type "so"
|
||||
:defaults (or *compile-file-truename* *load-truename*)))
|
||||
|
||||
;;; check libtest version
|
||||
(defparameter *required-dll-version* "20120107")
|
||||
|
||||
(defcvar "dll_version" :string)
|
||||
|
||||
(unless (string= *dll-version* *required-dll-version*)
|
||||
(error "version check failed: expected ~s but libtest reports ~s"
|
||||
*required-dll-version*
|
||||
*dll-version*))
|
||||
|
||||
;;; The maximum and minimum values for single and double precision C
|
||||
;;; floating point values, which may be quite different from the
|
||||
;;; corresponding Lisp versions.
|
||||
(defcvar "float_max" :float)
|
||||
(defcvar "float_min" :float)
|
||||
(defcvar "double_max" :double)
|
||||
(defcvar "double_min" :double)
|
||||
|
||||
(defun run-cffi-tests (&key (compiled nil))
|
||||
(let ((regression-test::*compile-tests* compiled)
|
||||
(*package* (find-package '#:cffi-tests)))
|
||||
(format t "~&;;; running tests (~Acompiled)" (if compiled "" "un"))
|
||||
(do-tests)
|
||||
(set-difference (regression-test:pending-tests)
|
||||
regression-test::*expected-failures*)))
|
||||
|
||||
(defun run-all-cffi-tests ()
|
||||
(append (run-cffi-tests :compiled nil)
|
||||
(run-cffi-tests :compiled t)))
|
||||
|
||||
(defmacro expecting-error (&body body)
|
||||
`(handler-case (progn ,@body :no-error)
|
||||
(error () :error)))
|
||||
|
|
@ -0,0 +1,526 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; callbacks.lisp --- Tests on callbacks.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(defcfun "expect_char_sum" :int (f :pointer))
|
||||
(defcfun "expect_unsigned_char_sum" :int (f :pointer))
|
||||
(defcfun "expect_short_sum" :int (f :pointer))
|
||||
(defcfun "expect_unsigned_short_sum" :int (f :pointer))
|
||||
(defcfun "expect_int_sum" :int (f :pointer))
|
||||
(defcfun "expect_unsigned_int_sum" :int (f :pointer))
|
||||
(defcfun "expect_long_sum" :int (f :pointer))
|
||||
(defcfun "expect_unsigned_long_sum" :int (f :pointer))
|
||||
(defcfun "expect_float_sum" :int (f :pointer))
|
||||
(defcfun "expect_double_sum" :int (f :pointer))
|
||||
(defcfun "expect_pointer_sum" :int (f :pointer))
|
||||
(defcfun "expect_strcat" :int (f :pointer))
|
||||
|
||||
#-cffi-sys::no-long-long
|
||||
(progn
|
||||
(defcfun "expect_long_long_sum" :int (f :pointer))
|
||||
(defcfun "expect_unsigned_long_long_sum" :int (f :pointer)))
|
||||
|
||||
#+(and scl long-float)
|
||||
(defcfun "expect_long_double_sum" :int (f :pointer))
|
||||
|
||||
(defcallback sum-char :char ((a :char) (b :char))
|
||||
"Test if the named block is present and the docstring too."
|
||||
;(format t "~%}}} a: ~A, b: ~A {{{~%" a b)
|
||||
(return-from sum-char (+ a b)))
|
||||
|
||||
(defcallback sum-unsigned-char :unsigned-char
|
||||
((a :unsigned-char) (b :unsigned-char))
|
||||
;(format t "~%}}} a: ~A, b: ~A {{{~%" a b)
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-short :short ((a :short) (b :short))
|
||||
;(format t "~%}}} a: ~A, b: ~A {{{~%" a b)
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-unsigned-short :unsigned-short
|
||||
((a :unsigned-short) (b :unsigned-short))
|
||||
;(format t "~%}}} a: ~A, b: ~A {{{~%" a b)
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-int :int ((a :int) (b :int))
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-unsigned-int :unsigned-int
|
||||
((a :unsigned-int) (b :unsigned-int))
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-long :long ((a :long) (b :long))
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-unsigned-long :unsigned-long
|
||||
((a :unsigned-long) (b :unsigned-long))
|
||||
(+ a b))
|
||||
|
||||
#-cffi-sys::no-long-long
|
||||
(progn
|
||||
(defcallback sum-long-long :long-long
|
||||
((a :long-long) (b :long-long))
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-unsigned-long-long :unsigned-long-long
|
||||
((a :unsigned-long-long) (b :unsigned-long-long))
|
||||
(+ a b)))
|
||||
|
||||
(defcallback sum-float :float ((a :float) (b :float))
|
||||
;(format t "~%}}} a: ~A, b: ~A {{{~%" a b)
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-double :double ((a :double) (b :double))
|
||||
;(format t "~%}}} a: ~A, b: ~A {{{~%" a b)
|
||||
(+ a b))
|
||||
|
||||
#+(and scl long-float)
|
||||
(defcallback sum-long-double :long-double ((a :long-double) (b :long-double))
|
||||
;(format t "~%}}} a: ~A, b: ~A {{{~%" a b)
|
||||
(+ a b))
|
||||
|
||||
(defcallback sum-pointer :pointer ((ptr :pointer) (offset :int))
|
||||
(inc-pointer ptr offset))
|
||||
|
||||
(defcallback lisp-strcat :string ((a :string) (b :string))
|
||||
(concatenate 'string a b))
|
||||
|
||||
(deftest callbacks.char
|
||||
(expect-char-sum (get-callback 'sum-char))
|
||||
1)
|
||||
|
||||
(deftest callbacks.unsigned-char
|
||||
(expect-unsigned-char-sum (get-callback 'sum-unsigned-char))
|
||||
1)
|
||||
|
||||
(deftest callbacks.short
|
||||
(expect-short-sum (callback sum-short))
|
||||
1)
|
||||
|
||||
(deftest callbacks.unsigned-short
|
||||
(expect-unsigned-short-sum (callback sum-unsigned-short))
|
||||
1)
|
||||
|
||||
(deftest callbacks.int
|
||||
(expect-int-sum (callback sum-int))
|
||||
1)
|
||||
|
||||
(deftest callbacks.unsigned-int
|
||||
(expect-unsigned-int-sum (callback sum-unsigned-int))
|
||||
1)
|
||||
|
||||
(deftest callbacks.long
|
||||
(expect-long-sum (callback sum-long))
|
||||
1)
|
||||
|
||||
(deftest callbacks.unsigned-long
|
||||
(expect-unsigned-long-sum (callback sum-unsigned-long))
|
||||
1)
|
||||
|
||||
#-cffi-sys::no-long-long
|
||||
(progn
|
||||
(deftest (callbacks.long-long :expected-to-fail (alexandria:featurep :openmcl))
|
||||
(expect-long-long-sum (callback sum-long-long))
|
||||
1)
|
||||
|
||||
(deftest callbacks.unsigned-long-long
|
||||
(expect-unsigned-long-long-sum (callback sum-unsigned-long-long))
|
||||
1))
|
||||
|
||||
(deftest callbacks.float
|
||||
(expect-float-sum (callback sum-float))
|
||||
1)
|
||||
|
||||
(deftest callbacks.double
|
||||
(expect-double-sum (callback sum-double))
|
||||
1)
|
||||
|
||||
#+(and scl long-float)
|
||||
(deftest callbacks.long-double
|
||||
(expect-long-double-sum (callback sum-long-double))
|
||||
1)
|
||||
|
||||
(deftest callbacks.pointer
|
||||
(expect-pointer-sum (callback sum-pointer))
|
||||
1)
|
||||
|
||||
(deftest callbacks.string
|
||||
(expect-strcat (callback lisp-strcat))
|
||||
1)
|
||||
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(defcallback return-a-string-not-nil :string ()
|
||||
"abc")
|
||||
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(deftest callbacks.string-not-docstring
|
||||
(foreign-funcall-pointer (callback return-a-string-not-nil) () :string)
|
||||
"abc")
|
||||
|
||||
(defcallback check-for-nil :boolean ((pointer :pointer))
|
||||
(null pointer))
|
||||
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(deftest callbacks.nil-for-null
|
||||
(foreign-funcall-pointer (callback check-for-nil) nil
|
||||
:pointer (null-pointer) :boolean)
|
||||
nil)
|
||||
|
||||
;;; This one tests mem-aref too.
|
||||
(defcfun "qsort" :void
|
||||
(base :pointer)
|
||||
(nmemb :int)
|
||||
(size :int)
|
||||
(fun-compar :pointer))
|
||||
|
||||
(defcallback < :int ((a :pointer) (b :pointer))
|
||||
(let ((x (mem-ref a :int))
|
||||
(y (mem-ref b :int)))
|
||||
(cond ((> x y) 1)
|
||||
((< x y) -1)
|
||||
(t 0))))
|
||||
|
||||
(deftest callbacks.qsort
|
||||
(with-foreign-object (array :int 10)
|
||||
;; Initialize array.
|
||||
(loop for i from 0 and n in '(7 2 10 4 3 5 1 6 9 8)
|
||||
do (setf (mem-aref array :int i) n))
|
||||
;; Sort it.
|
||||
(qsort array 10 (foreign-type-size :int) (callback <))
|
||||
;; Return it as a list.
|
||||
(loop for i from 0 below 10
|
||||
collect (mem-aref array :int i)))
|
||||
(1 2 3 4 5 6 7 8 9 10))
|
||||
|
||||
;;; void callback
|
||||
(defparameter *int* -1)
|
||||
|
||||
(defcfun "pass_int_ref" :void (f :pointer))
|
||||
|
||||
;;; CMUCL chokes on this one for some reason.
|
||||
#-(and darwin cmucl)
|
||||
(defcallback read-int-from-pointer :void ((a :pointer))
|
||||
(setq *int* (mem-ref a :int)))
|
||||
|
||||
#+(and darwin cmucl)
|
||||
(pushnew 'callbacks.void rt::*expected-failures*)
|
||||
|
||||
(deftest callbacks.void
|
||||
(progn
|
||||
(pass-int-ref (callback read-int-from-pointer))
|
||||
*int*)
|
||||
1984)
|
||||
|
||||
;;; test funcalling of a callback and also declarations inside
|
||||
;;; callbacks.
|
||||
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(progn
|
||||
(defcallback sum-2 :int ((a :int) (b :int) (c :int))
|
||||
(declare (ignore c))
|
||||
(+ a b))
|
||||
|
||||
(deftest callbacks.funcall.1
|
||||
(foreign-funcall-pointer (callback sum-2) () :int 2 :int 3 :int 1 :int)
|
||||
5)
|
||||
|
||||
(defctype foo-float :float)
|
||||
|
||||
(defcallback sum-2f foo-float
|
||||
((a foo-float) (b foo-float) (c foo-float) (d foo-float) (e foo-float))
|
||||
"This one ignores the middle 3 arguments."
|
||||
(declare (ignore b c))
|
||||
(declare (ignore d))
|
||||
(+ a e))
|
||||
|
||||
(deftest callbacks.funcall.2
|
||||
(foreign-funcall-pointer (callback sum-2f) () foo-float 1.0 foo-float 2.0
|
||||
foo-float 3.0 foo-float 4.0 foo-float 5.0
|
||||
foo-float)
|
||||
6.0))
|
||||
|
||||
;;; (cb-test :no-long-long t)
|
||||
|
||||
(defcfun "call_sum_127_no_ll" :long (cb :pointer))
|
||||
|
||||
;;; CMUCL and CCL choke on this one.
|
||||
#-(or cmucl clozure
|
||||
#.(cl:if (cl:>= cl:lambda-parameters-limit 127) '(:or) '(:and)))
|
||||
(defcallback sum-127-no-ll :long
|
||||
((a1 :unsigned-long) (a2 :pointer) (a3 :long) (a4 :double)
|
||||
(a5 :unsigned-long) (a6 :float) (a7 :float) (a8 :int) (a9 :unsigned-int)
|
||||
(a10 :double) (a11 :double) (a12 :double) (a13 :pointer)
|
||||
(a14 :unsigned-short) (a15 :unsigned-short) (a16 :pointer) (a17 :long)
|
||||
(a18 :long) (a19 :int) (a20 :short) (a21 :unsigned-short)
|
||||
(a22 :unsigned-short) (a23 :char) (a24 :long) (a25 :pointer) (a26 :pointer)
|
||||
(a27 :char) (a28 :unsigned-char) (a29 :unsigned-long) (a30 :short)
|
||||
(a31 :int) (a32 :int) (a33 :unsigned-char) (a34 :short) (a35 :long)
|
||||
(a36 :long) (a37 :pointer) (a38 :unsigned-short) (a39 :char) (a40 :double)
|
||||
(a41 :unsigned-short) (a42 :pointer) (a43 :short) (a44 :unsigned-long)
|
||||
(a45 :unsigned-short) (a46 :float) (a47 :unsigned-char) (a48 :short)
|
||||
(a49 :float) (a50 :short) (a51 :char) (a52 :unsigned-long)
|
||||
(a53 :unsigned-long) (a54 :char) (a55 :float) (a56 :long) (a57 :pointer)
|
||||
(a58 :short) (a59 :float) (a60 :unsigned-int) (a61 :float)
|
||||
(a62 :unsigned-int) (a63 :double) (a64 :unsigned-int) (a65 :unsigned-char)
|
||||
(a66 :int) (a67 :long) (a68 :char) (a69 :short) (a70 :double) (a71 :int)
|
||||
(a72 :pointer) (a73 :char) (a74 :unsigned-short) (a75 :pointer)
|
||||
(a76 :unsigned-short) (a77 :pointer) (a78 :unsigned-long) (a79 :double)
|
||||
(a80 :pointer) (a81 :long) (a82 :float) (a83 :unsigned-short)
|
||||
(a84 :unsigned-short) (a85 :pointer) (a86 :float) (a87 :int)
|
||||
(a88 :unsigned-int) (a89 :double) (a90 :float) (a91 :long) (a92 :pointer)
|
||||
(a93 :unsigned-short) (a94 :float) (a95 :unsigned-char) (a96 :unsigned-char)
|
||||
(a97 :float) (a98 :unsigned-int) (a99 :float) (a100 :unsigned-short)
|
||||
(a101 :double) (a102 :unsigned-short) (a103 :unsigned-long)
|
||||
(a104 :unsigned-int) (a105 :unsigned-long) (a106 :pointer)
|
||||
(a107 :unsigned-char) (a108 :char) (a109 :char) (a110 :unsigned-short)
|
||||
(a111 :unsigned-long) (a112 :float) (a113 :short) (a114 :pointer)
|
||||
(a115 :long) (a116 :unsigned-short) (a117 :short) (a118 :double)
|
||||
(a119 :short) (a120 :int) (a121 :char) (a122 :unsigned-long) (a123 :long)
|
||||
(a124 :int) (a125 :pointer) (a126 :double) (a127 :unsigned-char))
|
||||
(let ((args (list a1 (pointer-address a2) a3 (floor a4) a5 (floor a6)
|
||||
(floor a7) a8 a9 (floor a10) (floor a11) (floor a12)
|
||||
(pointer-address a13) a14 a15 (pointer-address a16) a17 a18
|
||||
a19 a20 a21 a22 a23 a24 (pointer-address a25)
|
||||
(pointer-address a26) a27 a28 a29 a30 a31 a32 a33 a34 a35
|
||||
a36 (pointer-address a37) a38 a39 (floor a40) a41
|
||||
(pointer-address a42) a43 a44 a45 (floor a46) a47 a48
|
||||
(floor a49) a50 a51 a52 a53 a54 (floor a55) a56
|
||||
(pointer-address a57) a58 (floor a59) a60 (floor a61) a62
|
||||
(floor a63) a64 a65 a66 a67 a68 a69 (floor a70) a71
|
||||
(pointer-address a72) a73 a74 (pointer-address a75) a76
|
||||
(pointer-address a77) a78 (floor a79) (pointer-address a80)
|
||||
a81 (floor a82) a83 a84 (pointer-address a85) (floor a86)
|
||||
a87 a88 (floor a89) (floor a90) a91 (pointer-address a92)
|
||||
a93 (floor a94) a95 a96 (floor a97) a98 (floor a99) a100
|
||||
(floor a101) a102 a103 a104 a105 (pointer-address a106) a107
|
||||
a108 a109 a110 a111 (floor a112) a113 (pointer-address a114)
|
||||
a115 a116 a117 (floor a118) a119 a120 a121 a122 a123 a124
|
||||
(pointer-address a125) (floor a126) a127)))
|
||||
#-(and)
|
||||
(loop for i from 1 and arg in args do
|
||||
(format t "a~A: ~A~%" i arg))
|
||||
(reduce #'+ args)))
|
||||
|
||||
#+(or openmcl cmucl (and darwin (or allegro lispworks)))
|
||||
(push 'callbacks.bff.1 regression-test::*expected-failures*)
|
||||
|
||||
#+#.(cl:if (cl:>= cl:lambda-parameters-limit 127) '(:and) '(:or))
|
||||
(deftest callbacks.bff.1
|
||||
(call-sum-127-no-ll (callback sum-127-no-ll))
|
||||
2008547941)
|
||||
|
||||
;;; (cb-test)
|
||||
|
||||
#-(or cffi-sys::no-long-long
|
||||
#.(cl:if (cl:>= cl:lambda-parameters-limit 127) '(or) '(and)))
|
||||
(progn
|
||||
(defcfun "call_sum_127" :long-long (cb :pointer))
|
||||
|
||||
;;; CMUCL and CCL choke on this one.
|
||||
#-(or cmucl clozure)
|
||||
(defcallback sum-127 :long-long
|
||||
((a1 :short) (a2 :char) (a3 :pointer) (a4 :float) (a5 :long) (a6 :double)
|
||||
(a7 :unsigned-long-long) (a8 :unsigned-short) (a9 :unsigned-char)
|
||||
(a10 :char) (a11 :char) (a12 :unsigned-short) (a13 :unsigned-long-long)
|
||||
(a14 :unsigned-short) (a15 :long-long) (a16 :unsigned-short)
|
||||
(a17 :unsigned-long-long) (a18 :unsigned-char) (a19 :unsigned-char)
|
||||
(a20 :unsigned-long-long) (a21 :long-long) (a22 :char) (a23 :float)
|
||||
(a24 :unsigned-int) (a25 :float) (a26 :float) (a27 :unsigned-int)
|
||||
(a28 :float) (a29 :char) (a30 :unsigned-char) (a31 :long) (a32 :long-long)
|
||||
(a33 :unsigned-char) (a34 :double) (a35 :long) (a36 :double)
|
||||
(a37 :unsigned-int) (a38 :unsigned-short) (a39 :long-long)
|
||||
(a40 :unsigned-int) (a41 :int) (a42 :unsigned-long-long) (a43 :long)
|
||||
(a44 :short) (a45 :unsigned-int) (a46 :unsigned-int)
|
||||
(a47 :unsigned-long-long) (a48 :unsigned-int) (a49 :long) (a50 :pointer)
|
||||
(a51 :unsigned-char) (a52 :char) (a53 :long-long) (a54 :unsigned-short)
|
||||
(a55 :unsigned-int) (a56 :float) (a57 :unsigned-char) (a58 :unsigned-long)
|
||||
(a59 :long-long) (a60 :float) (a61 :long) (a62 :float) (a63 :int)
|
||||
(a64 :float) (a65 :unsigned-short) (a66 :unsigned-long-long) (a67 :short)
|
||||
(a68 :unsigned-long) (a69 :long) (a70 :char) (a71 :unsigned-short)
|
||||
(a72 :long-long) (a73 :short) (a74 :double) (a75 :pointer)
|
||||
(a76 :unsigned-int) (a77 :char) (a78 :unsigned-int) (a79 :pointer)
|
||||
(a80 :pointer) (a81 :unsigned-char) (a82 :pointer) (a83 :unsigned-short)
|
||||
(a84 :unsigned-char) (a85 :long) (a86 :pointer) (a87 :char) (a88 :long)
|
||||
(a89 :unsigned-short) (a90 :unsigned-char) (a91 :double)
|
||||
(a92 :unsigned-long-long) (a93 :unsigned-short) (a94 :unsigned-short)
|
||||
(a95 :unsigned-int) (a96 :long) (a97 :char) (a98 :long) (a99 :char)
|
||||
(a100 :short) (a101 :unsigned-short) (a102 :unsigned-long)
|
||||
(a103 :unsigned-long) (a104 :short) (a105 :long-long) (a106 :long-long)
|
||||
(a107 :long-long) (a108 :double) (a109 :unsigned-short)
|
||||
(a110 :unsigned-char) (a111 :short) (a112 :unsigned-char) (a113 :long)
|
||||
(a114 :long-long) (a115 :unsigned-long-long) (a116 :unsigned-int)
|
||||
(a117 :unsigned-long) (a118 :unsigned-char) (a119 :long-long)
|
||||
(a120 :unsigned-char) (a121 :unsigned-long-long) (a122 :double)
|
||||
(a123 :unsigned-char) (a124 :long-long) (a125 :unsigned-char)
|
||||
(a126 :char) (a127 :long-long))
|
||||
(+ a1 a2 (pointer-address a3) (values (floor a4)) a5 (values (floor a6))
|
||||
a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22
|
||||
(values (floor a23)) a24 (values (floor a25)) (values (floor a26))
|
||||
a27 (values (floor a28)) a29 a30 a31 a32 a33 (values (floor a34))
|
||||
a35 (values (floor a36)) a37 a38 a39 a40 a41 a42 a43 a44 a45 a46 a47
|
||||
a48 a49 (pointer-address a50) a51 a52 a53 a54 a55 (values (floor a56))
|
||||
a57 a58 a59 (values (floor a60)) a61 (values (floor a62)) a63
|
||||
(values (floor a64)) a65 a66 a67 a68 a69 a70 a71 a72 a73
|
||||
(values (floor a74)) (pointer-address a75) a76 a77 a78
|
||||
(pointer-address a79) (pointer-address a80) a81 (pointer-address a82)
|
||||
a83 a84 a85 (pointer-address a86) a87 a88 a89 a90 (values (floor a91))
|
||||
a92 a93 a94 a95 a96 a97 a98 a99 a100 a101 a102 a103 a104 a105 a106 a107
|
||||
(values (floor a108)) a109 a110 a111 a112 a113 a114 a115 a116 a117 a118
|
||||
a119 a120 a121 (values (floor a122)) a123 a124 a125 a126 a127))
|
||||
|
||||
#+(or openmcl cmucl)
|
||||
(push 'callbacks.bff.2 rt::*expected-failures*)
|
||||
|
||||
(deftest callbacks.bff.2
|
||||
(call-sum-127 (callback sum-127))
|
||||
8166570665645582011))
|
||||
|
||||
;;; regression test: (callback non-existant-callback) should throw an error
|
||||
(deftest callbacks.non-existant
|
||||
(not (null (nth-value 1 (ignore-errors (callback doesnt-exist)))))
|
||||
t)
|
||||
|
||||
;;; Handling many arguments of type double. Many lisps (used to) fail
|
||||
;;; this one on darwin/ppc. This test might be bogus due to floating
|
||||
;;; point arithmetic rounding errors.
|
||||
;;;
|
||||
;;; CMUCL chokes on this one.
|
||||
#-(and darwin cmucl)
|
||||
(defcallback double26 :double
|
||||
((a1 :double) (a2 :double) (a3 :double) (a4 :double) (a5 :double)
|
||||
(a6 :double) (a7 :double) (a8 :double) (a9 :double) (a10 :double)
|
||||
(a11 :double) (a12 :double) (a13 :double) (a14 :double) (a15 :double)
|
||||
(a16 :double) (a17 :double) (a18 :double) (a19 :double) (a20 :double)
|
||||
(a21 :double) (a22 :double) (a23 :double) (a24 :double) (a25 :double)
|
||||
(a26 :double))
|
||||
(let ((args (list a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15
|
||||
a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26)))
|
||||
#-(and)
|
||||
(loop for i from 1 and arg in args do
|
||||
(format t "a~A: ~A~%" i arg))
|
||||
(reduce #'+ args)))
|
||||
|
||||
(defcfun "call_double26" :double (f :pointer))
|
||||
|
||||
#+(and darwin (or allegro cmucl))
|
||||
(pushnew 'callbacks.double26 rt::*expected-failures*)
|
||||
|
||||
(deftest callbacks.double26
|
||||
(call-double26 (callback double26))
|
||||
81.64d0)
|
||||
|
||||
#+(and darwin cmucl)
|
||||
(pushnew 'callbacks.double26.funcall rt::*expected-failures*)
|
||||
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(deftest callbacks.double26.funcall
|
||||
(foreign-funcall-pointer
|
||||
(callback double26) () :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double)
|
||||
81.64d0)
|
||||
|
||||
;;; Same as above, for floats.
|
||||
#-(and darwin cmucl)
|
||||
(defcallback float26 :float
|
||||
((a1 :float) (a2 :float) (a3 :float) (a4 :float) (a5 :float)
|
||||
(a6 :float) (a7 :float) (a8 :float) (a9 :float) (a10 :float)
|
||||
(a11 :float) (a12 :float) (a13 :float) (a14 :float) (a15 :float)
|
||||
(a16 :float) (a17 :float) (a18 :float) (a19 :float) (a20 :float)
|
||||
(a21 :float) (a22 :float) (a23 :float) (a24 :float) (a25 :float)
|
||||
(a26 :float))
|
||||
(let ((args (list a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15
|
||||
a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26)))
|
||||
#-(and)
|
||||
(loop for i from 1 and arg in args do
|
||||
(format t "a~A: ~A~%" i arg))
|
||||
(reduce #'+ args)))
|
||||
|
||||
(defcfun "call_float26" :float (f :pointer))
|
||||
|
||||
#+(and darwin (or lispworks openmcl cmucl))
|
||||
(pushnew 'callbacks.float26 regression-test::*expected-failures*)
|
||||
|
||||
(deftest callbacks.float26
|
||||
(call-float26 (callback float26))
|
||||
130.0)
|
||||
|
||||
#+(and darwin (or lispworks openmcl cmucl))
|
||||
(pushnew 'callbacks.float26.funcall regression-test::*expected-failures*)
|
||||
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(deftest callbacks.float26.funcall
|
||||
(foreign-funcall-pointer
|
||||
(callback float26) () :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float)
|
||||
130.0)
|
||||
|
||||
;;; Defining a callback as a non-toplevel form. Not portable. Doesn't
|
||||
;;; work for CMUCL or Allegro.
|
||||
#-(and)
|
||||
(let ((n 42))
|
||||
(defcallback non-toplevel-cb :int ()
|
||||
n))
|
||||
|
||||
#-(and)
|
||||
(deftest callbacks.non-toplevel
|
||||
(foreign-funcall (callback non-toplevel-cb) :int)
|
||||
42)
|
||||
|
||||
;;;# Stdcall
|
||||
|
||||
#+(and x86 (not cffi-sys::no-stdcall))
|
||||
(progn
|
||||
(defcallback (stdcall-cb :convention :stdcall) :int
|
||||
((a :int) (b :int) (c :int))
|
||||
(+ a b c))
|
||||
|
||||
(defcfun "call_stdcall_fun" :int
|
||||
(f :pointer))
|
||||
|
||||
(deftest callbacks.stdcall.1
|
||||
(call-stdcall-fun (callback stdcall-cb))
|
||||
42))
|
||||
|
||||
;;; RT: many of the %DEFCALLBACK implementations wouldn't handle
|
||||
;;; uninterned symbols.
|
||||
(deftest callbacks.uninterned
|
||||
(values (defcallback #1=#:foo :void ())
|
||||
(pointerp (callback #1#)))
|
||||
#1# t)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
rem
|
||||
rem script for compiling the test lib with the free MSVC++ toolkit.
|
||||
rem
|
||||
|
||||
cl /LD /DWIN32=1 /Tc libtest.c
|
||||
del libtest.obj libtest.exp
|
||||
|
||||
cl /LD /DWIN32=1 /Tc libtest2.c
|
||||
del libtest2.obj libtest2.exp
|
||||
|
|
@ -0,0 +1,536 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; defcfun.lisp --- Tests function definition and calling.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2007, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(deftest defcfun.parse-name-and-options.1
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(let ((*package* (find-package '#:cffi-tests)))
|
||||
(cffi::parse-name-and-options "foo_bar"))
|
||||
(list lisp-name foreign-name))
|
||||
(foo-bar "foo_bar"))
|
||||
|
||||
(deftest defcfun.parse-name-and-options.2
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(let ((*package* (find-package '#:cffi-tests)))
|
||||
(cffi::parse-name-and-options "foo_bar" t))
|
||||
(list lisp-name foreign-name))
|
||||
(*foo-bar* "foo_bar"))
|
||||
|
||||
(deftest defcfun.parse-name-and-options.3
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(cffi::parse-name-and-options 'foo-bar)
|
||||
(list lisp-name foreign-name))
|
||||
(foo-bar "foo_bar"))
|
||||
|
||||
(deftest defcfun.parse-name-and-options.4
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(cffi::parse-name-and-options '*foo-bar* t)
|
||||
(list lisp-name foreign-name))
|
||||
(*foo-bar* "foo_bar"))
|
||||
|
||||
(deftest defcfun.parse-name-and-options.5
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(cffi::parse-name-and-options '("foo_bar" foo-baz))
|
||||
(list lisp-name foreign-name))
|
||||
(foo-baz "foo_bar"))
|
||||
|
||||
(deftest defcfun.parse-name-and-options.6
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(cffi::parse-name-and-options '("foo_bar" *foo-baz*) t)
|
||||
(list lisp-name foreign-name))
|
||||
(*foo-baz* "foo_bar"))
|
||||
|
||||
(deftest defcfun.parse-name-and-options.7
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(cffi::parse-name-and-options '(foo-baz "foo_bar"))
|
||||
(list lisp-name foreign-name))
|
||||
(foo-baz "foo_bar"))
|
||||
|
||||
(deftest defcfun.parse-name-and-options.8
|
||||
(multiple-value-bind (lisp-name foreign-name)
|
||||
(cffi::parse-name-and-options '(*foo-baz* "foo_bar") t)
|
||||
(list lisp-name foreign-name))
|
||||
(*foo-baz* "foo_bar"))
|
||||
|
||||
;;;# Name translation
|
||||
|
||||
(deftest translate-underscore-separated-name.to-symbol
|
||||
(let ((*package* (find-package '#:cffi-tests)))
|
||||
(translate-underscore-separated-name "some_name_with_underscores"))
|
||||
some-name-with-underscores)
|
||||
|
||||
(deftest translate-underscore-separated-name.to-string
|
||||
(translate-underscore-separated-name 'some-name-with-underscores)
|
||||
"some_name_with_underscores")
|
||||
|
||||
(deftest translate-camelcase-name.to-symbol
|
||||
(let ((*package* (find-package '#:cffi-tests)))
|
||||
(translate-camelcase-name "someXmlFunction"))
|
||||
some-xml-function)
|
||||
|
||||
(deftest translate-camelcase-name.to-string
|
||||
(translate-camelcase-name 'some-xml-function)
|
||||
"someXmlFunction")
|
||||
|
||||
(deftest translate-camelcase-name.to-string-upper
|
||||
(translate-camelcase-name 'some-xml-function :upper-initial-p t)
|
||||
"SomeXmlFunction")
|
||||
|
||||
(deftest translate-camelcase-name.to-symbol-special
|
||||
(let ((*package* (find-package '#:cffi-tests)))
|
||||
(translate-camelcase-name "someXMLFunction" :special-words '("XML")))
|
||||
some-xml-function)
|
||||
|
||||
(deftest translate-camelcase-name.to-string-special
|
||||
(translate-camelcase-name 'some-xml-function :special-words '("XML"))
|
||||
"someXMLFunction")
|
||||
|
||||
(deftest translate-name-from-foreign.function
|
||||
(let ((*package* (find-package '#:cffi-tests)))
|
||||
(translate-name-from-foreign "some_xml_name" *package*))
|
||||
some-xml-name)
|
||||
|
||||
(deftest translate-name-from-foreign.var
|
||||
(let ((*package* (find-package '#:cffi-tests)))
|
||||
(translate-name-from-foreign "some_xml_name" *package* t))
|
||||
*some-xml-name*)
|
||||
|
||||
(deftest translate-name-to-foreign.function
|
||||
(translate-name-to-foreign 'some-xml-name *package*)
|
||||
"some_xml_name")
|
||||
|
||||
(deftest translate-name-to-foreign.var
|
||||
(translate-name-to-foreign '*some-xml-name* *package* t)
|
||||
"some_xml_name")
|
||||
|
||||
;;;# Calling with built-in c types
|
||||
;;;
|
||||
;;; Tests calling standard C library functions both passing
|
||||
;;; and returning each built-in type. (adapted from funcall.lisp)
|
||||
|
||||
(defcfun "toupper" :char
|
||||
"toupper docstring"
|
||||
(char :char))
|
||||
|
||||
(deftest defcfun.char
|
||||
(toupper (char-code #\a))
|
||||
#.(char-code #\A))
|
||||
|
||||
(deftest defcfun.docstring
|
||||
(documentation 'toupper 'function)
|
||||
"toupper docstring")
|
||||
|
||||
|
||||
(defcfun ("abs" c-abs) :int
|
||||
(n :int))
|
||||
|
||||
(deftest defcfun.int
|
||||
(c-abs -100)
|
||||
100)
|
||||
|
||||
|
||||
(defcfun "labs" :long
|
||||
(n :long))
|
||||
|
||||
(deftest defcfun.long
|
||||
(labs -131072)
|
||||
131072)
|
||||
|
||||
|
||||
#-cffi-features:no-long-long
|
||||
(progn
|
||||
(defcfun "my_llabs" :long-long
|
||||
(n :long-long))
|
||||
|
||||
(deftest defcfun.long-long
|
||||
(my-llabs -9223372036854775807)
|
||||
9223372036854775807)
|
||||
|
||||
(defcfun "ullong" :unsigned-long-long
|
||||
(n :unsigned-long-long))
|
||||
|
||||
#+allegro ; lp#914500
|
||||
(pushnew 'defcfun.unsigned-long-long rt::*expected-failures*)
|
||||
|
||||
(deftest defcfun.unsigned-long-long
|
||||
(let ((ullong-max (1- (expt 2 (* 8 (foreign-type-size :unsigned-long-long))))))
|
||||
(eql ullong-max (ullong ullong-max)))
|
||||
t))
|
||||
|
||||
|
||||
(defcfun "my_sqrtf" :float
|
||||
(n :float))
|
||||
|
||||
(deftest defcfun.float
|
||||
(my-sqrtf 16.0)
|
||||
4.0)
|
||||
|
||||
|
||||
(defcfun ("sqrt" c-sqrt) :double
|
||||
(n :double))
|
||||
|
||||
(deftest defcfun.double
|
||||
(c-sqrt 36.0d0)
|
||||
6.0d0)
|
||||
|
||||
|
||||
#+(and scl long-float)
|
||||
(defcfun ("sqrtl" c-sqrtl) :long-double
|
||||
(n :long-double))
|
||||
|
||||
#+(and scl long-float)
|
||||
(deftest defcfun.long-double
|
||||
(c-sqrtl 36.0l0)
|
||||
6.0l0)
|
||||
|
||||
|
||||
(defcfun "strlen" :int
|
||||
(n :string))
|
||||
|
||||
(deftest defcfun.string.1
|
||||
(strlen "Hello")
|
||||
5)
|
||||
|
||||
|
||||
(defcfun "strcpy" (:pointer :char)
|
||||
(dest (:pointer :char))
|
||||
(src :string))
|
||||
|
||||
(defcfun "strcat" (:pointer :char)
|
||||
(dest (:pointer :char))
|
||||
(src :string))
|
||||
|
||||
(deftest defcfun.string.2
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(strcpy s "Hello")
|
||||
(strcat s ", world!"))
|
||||
"Hello, world!")
|
||||
|
||||
(defcfun "strerror" :string
|
||||
(n :int))
|
||||
|
||||
(deftest defcfun.string.3
|
||||
(typep (strerror 1) 'string)
|
||||
t)
|
||||
|
||||
|
||||
;;; Regression test. Allegro would warn on direct calls to
|
||||
;;; functions with no arguments.
|
||||
;;;
|
||||
;;; Also, let's check if void functions will return NIL.
|
||||
;;;
|
||||
;;; Check if a docstring without arguments doesn't cause problems.
|
||||
|
||||
(defcfun "noargs" :int
|
||||
"docstring")
|
||||
|
||||
(deftest defcfun.noargs
|
||||
(noargs)
|
||||
42)
|
||||
|
||||
(defcfun "noop" :void)
|
||||
|
||||
#+(or allegro openmcl ecl) (pushnew 'defcfun.noop rt::*expected-failures*)
|
||||
|
||||
(deftest defcfun.noop
|
||||
(noop)
|
||||
#|no values|#)
|
||||
|
||||
;;;# Calling varargs functions
|
||||
|
||||
(defcfun "sum_double_arbitrary" :double (n :int) &rest)
|
||||
|
||||
(deftest defcfun.varargs.nostdlib
|
||||
(sum-double-arbitrary
|
||||
26
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0)
|
||||
81.64d0)
|
||||
|
||||
(defcfun "sprintf" :int
|
||||
"sprintf docstring"
|
||||
(str (:pointer :char))
|
||||
(control :string)
|
||||
&rest)
|
||||
|
||||
;;; CLISP and ABCL discard macro docstrings.
|
||||
#+(or clisp abcl)
|
||||
(pushnew 'defcfun.varargs.docstrings rt::*expected-failures*)
|
||||
|
||||
(deftest defcfun.varargs.docstrings
|
||||
(documentation 'sprintf 'function)
|
||||
"sprintf docstring")
|
||||
|
||||
(deftest defcfun.varargs.char
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(sprintf s "%c" :char 65))
|
||||
"A")
|
||||
|
||||
(deftest defcfun.varargs.short
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(sprintf s "%d" :short 42))
|
||||
"42")
|
||||
|
||||
(deftest defcfun.varargs.int
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(sprintf s "%d" :int 1000))
|
||||
"1000")
|
||||
|
||||
(deftest defcfun.varargs.long
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(sprintf s "%ld" :long 131072))
|
||||
"131072")
|
||||
|
||||
(deftest defcfun.varargs.float
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(sprintf s "%.2f" :float (float pi)))
|
||||
"3.14")
|
||||
|
||||
(deftest defcfun.varargs.double
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(sprintf s "%.2f" :double (float pi 1.0d0)))
|
||||
"3.14")
|
||||
|
||||
#+(and scl long-float)
|
||||
(deftest defcfun.varargs.long-double
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(sprintf s "%.2Lf" :long-double pi))
|
||||
"3.14")
|
||||
|
||||
(deftest defcfun.varargs.string
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(sprintf s "%s, %s!" :string "Hello" :string "world"))
|
||||
"Hello, world!")
|
||||
|
||||
;;; (let ((rettype (find-type :long))
|
||||
;;; (arg-types (n-random-types-no-ll 127)))
|
||||
;;; (c-function rettype arg-types)
|
||||
;;; (gen-function-test rettype arg-types))
|
||||
|
||||
#+(and (not ecl)
|
||||
#.(cl:if (cl:>= cl:lambda-parameters-limit 127) '(:and) '(:or)))
|
||||
(progn
|
||||
(defcfun "sum_127_no_ll" :long
|
||||
(a1 :long) (a2 :unsigned-long) (a3 :short) (a4 :unsigned-short) (a5 :float)
|
||||
(a6 :double) (a7 :unsigned-long) (a8 :float) (a9 :unsigned-char)
|
||||
(a10 :unsigned-short) (a11 :short) (a12 :unsigned-long) (a13 :double)
|
||||
(a14 :long) (a15 :unsigned-int) (a16 :pointer) (a17 :unsigned-int)
|
||||
(a18 :unsigned-short) (a19 :long) (a20 :float) (a21 :pointer) (a22 :float)
|
||||
(a23 :int) (a24 :int) (a25 :unsigned-short) (a26 :long) (a27 :long)
|
||||
(a28 :double) (a29 :unsigned-char) (a30 :unsigned-int) (a31 :unsigned-int)
|
||||
(a32 :int) (a33 :unsigned-short) (a34 :unsigned-int) (a35 :pointer)
|
||||
(a36 :double) (a37 :double) (a38 :long) (a39 :short) (a40 :unsigned-short)
|
||||
(a41 :long) (a42 :char) (a43 :long) (a44 :unsigned-short) (a45 :pointer)
|
||||
(a46 :int) (a47 :unsigned-int) (a48 :double) (a49 :unsigned-char)
|
||||
(a50 :unsigned-char) (a51 :float) (a52 :int) (a53 :unsigned-short)
|
||||
(a54 :double) (a55 :short) (a56 :unsigned-char) (a57 :unsigned-long)
|
||||
(a58 :float) (a59 :float) (a60 :float) (a61 :pointer) (a62 :pointer)
|
||||
(a63 :unsigned-int) (a64 :unsigned-long) (a65 :char) (a66 :short)
|
||||
(a67 :unsigned-short) (a68 :unsigned-long) (a69 :pointer) (a70 :float)
|
||||
(a71 :double) (a72 :long) (a73 :unsigned-long) (a74 :short)
|
||||
(a75 :unsigned-int) (a76 :unsigned-short) (a77 :int) (a78 :unsigned-short)
|
||||
(a79 :char) (a80 :double) (a81 :short) (a82 :unsigned-char) (a83 :float)
|
||||
(a84 :char) (a85 :int) (a86 :double) (a87 :unsigned-char) (a88 :int)
|
||||
(a89 :unsigned-long) (a90 :double) (a91 :short) (a92 :short)
|
||||
(a93 :unsigned-int) (a94 :unsigned-char) (a95 :float) (a96 :long)
|
||||
(a97 :float) (a98 :long) (a99 :long) (a100 :int) (a101 :int)
|
||||
(a102 :unsigned-int) (a103 :char) (a104 :char) (a105 :unsigned-short)
|
||||
(a106 :unsigned-int) (a107 :unsigned-short) (a108 :unsigned-short)
|
||||
(a109 :int) (a110 :long) (a111 :char) (a112 :double) (a113 :unsigned-int)
|
||||
(a114 :char) (a115 :short) (a116 :unsigned-long) (a117 :unsigned-int)
|
||||
(a118 :short) (a119 :unsigned-char) (a120 :float) (a121 :pointer)
|
||||
(a122 :double) (a123 :int) (a124 :long) (a125 :char) (a126 :unsigned-short)
|
||||
(a127 :float))
|
||||
|
||||
(deftest defcfun.bff.1
|
||||
(sum-127-no-ll
|
||||
1442906394 520035521 -4715 50335 -13557.0 -30892.0d0 24061483 -23737.0
|
||||
22 2348 4986 104895680 8073.0d0 -571698147 102484400
|
||||
(make-pointer 507907275) 12733353 7824 -1275845284 13602.0
|
||||
(make-pointer 286958390) -8042.0 -773681663 -1289932452 31199 -154985357
|
||||
-170994216 16845.0d0 177 218969221 2794350893 6068863 26327 127699339
|
||||
(make-pointer 184352771) 18512.0d0 -12345.0d0 -179853040 -19981 37268
|
||||
-792845398 116 -1084653028 50494 (make-pointer 2105239646) -1710519651
|
||||
1557813312 2839.0d0 90 180 30580.0 -532698978 8623 9537.0d0 -10882 54
|
||||
184357206 14929.0 -8190.0 -25615.0 (make-pointer 235310526)
|
||||
(make-pointer 220476977) 7476055 1576685 -117 -11781 31479 23282640
|
||||
(make-pointer 8627281) -17834.0 10391.0d0 -1904504370 114393659 -17062
|
||||
637873619 16078 -891210259 8107 0 760.0d0 -21268 104 14133.0 10
|
||||
588598141 310.0d0 20 1351785456 16159552 -10121.0d0 -25866 24821
|
||||
68232851 60 -24132.0 -1660411658 13387.0 -786516668 -499825680
|
||||
-1128144619 111849719 2746091587 -2 95 14488 326328135 64781 18204
|
||||
150716680 -703859275 103 16809.0d0 852235610 -43 21088 242356110
|
||||
324325428 -22380 23 24814.0 (make-pointer 40362014) -14322.0d0
|
||||
-1864262539 523684371 -21 49995 -29175.0)
|
||||
796447501))
|
||||
|
||||
;;; (let ((rettype (find-type :long-long))
|
||||
;;; (arg-types (n-random-types 127)))
|
||||
;;; (c-function rettype arg-types)
|
||||
;;; (gen-function-test rettype arg-types))
|
||||
|
||||
#-(or ecl cffi-sys::no-long-long
|
||||
#.(cl:if (cl:>= cl:lambda-parameters-limit 127) '(:or) '(:and)))
|
||||
(progn
|
||||
(defcfun "sum_127" :long-long
|
||||
(a1 :pointer) (a2 :pointer) (a3 :float) (a4 :unsigned-long) (a5 :pointer)
|
||||
(a6 :long-long) (a7 :double) (a8 :double) (a9 :unsigned-short) (a10 :int)
|
||||
(a11 :long-long) (a12 :long) (a13 :short) (a14 :unsigned-int) (a15 :long)
|
||||
(a16 :unsigned-char) (a17 :int) (a18 :double) (a19 :short) (a20 :short)
|
||||
(a21 :long-long) (a22 :unsigned-int) (a23 :unsigned-short) (a24 :short)
|
||||
(a25 :pointer) (a26 :short) (a27 :unsigned-short) (a28 :unsigned-short)
|
||||
(a29 :int) (a30 :long-long) (a31 :pointer) (a32 :int) (a33 :unsigned-long)
|
||||
(a34 :unsigned-long) (a35 :pointer) (a36 :unsigned-long-long) (a37 :float)
|
||||
(a38 :int) (a39 :short) (a40 :pointer) (a41 :unsigned-long-long)
|
||||
(a42 :long-long) (a43 :unsigned-long) (a44 :unsigned-long)
|
||||
(a45 :unsigned-long-long) (a46 :unsigned-long) (a47 :char) (a48 :double)
|
||||
(a49 :long) (a50 :unsigned-int) (a51 :int) (a52 :short) (a53 :pointer)
|
||||
(a54 :long) (a55 :unsigned-long-long) (a56 :int) (a57 :unsigned-short)
|
||||
(a58 :unsigned-long-long) (a59 :float) (a60 :pointer) (a61 :float)
|
||||
(a62 :unsigned-short) (a63 :unsigned-long) (a64 :float) (a65 :unsigned-int)
|
||||
(a66 :unsigned-long-long) (a67 :pointer) (a68 :double)
|
||||
(a69 :unsigned-long-long) (a70 :double) (a71 :double) (a72 :long-long)
|
||||
(a73 :pointer) (a74 :unsigned-short) (a75 :long) (a76 :pointer) (a77 :short)
|
||||
(a78 :double) (a79 :long) (a80 :unsigned-char) (a81 :pointer)
|
||||
(a82 :unsigned-char) (a83 :long) (a84 :double) (a85 :pointer) (a86 :int)
|
||||
(a87 :double) (a88 :unsigned-char) (a89 :double) (a90 :short) (a91 :long)
|
||||
(a92 :int) (a93 :long) (a94 :double) (a95 :unsigned-short)
|
||||
(a96 :unsigned-int) (a97 :int) (a98 :char) (a99 :long-long) (a100 :double)
|
||||
(a101 :float) (a102 :unsigned-long) (a103 :short) (a104 :pointer)
|
||||
(a105 :float) (a106 :long-long) (a107 :int) (a108 :long-long)
|
||||
(a109 :long-long) (a110 :double) (a111 :unsigned-long-long) (a112 :double)
|
||||
(a113 :unsigned-long) (a114 :char) (a115 :char) (a116 :unsigned-long)
|
||||
(a117 :short) (a118 :unsigned-char) (a119 :unsigned-char) (a120 :int)
|
||||
(a121 :int) (a122 :float) (a123 :unsigned-char) (a124 :unsigned-char)
|
||||
(a125 :double) (a126 :unsigned-long-long) (a127 :char))
|
||||
|
||||
#+(and sbcl x86) (push 'defcfun.bff.2 rtest::*expected-failures*)
|
||||
|
||||
(deftest defcfun.bff.2
|
||||
(sum-127
|
||||
(make-pointer 2746181372) (make-pointer 177623060) -32334.0 3158055028
|
||||
(make-pointer 242315091) 4288001754991016425 -21047.0d0 287.0d0 18722
|
||||
243379286 -8677366518541007140 581399424 -13872 4240394881 1353358999
|
||||
226 969197676 -26207.0d0 6484 11150 1241680089902988480 106068320 61865
|
||||
2253 (make-pointer 866809333) -31613 35616 11715 1393601698
|
||||
8940888681199591845 (make-pointer 1524606024) 805638893 3315410736
|
||||
3432596795 (make-pointer 1490355706) 696175657106383698 -25438.0
|
||||
1294381547 26724 (make-pointer 3196569545) 2506913373410783697
|
||||
-4405955718732597856 4075932032 3224670123 2183829215657835866
|
||||
1318320964 -22 -3786.0d0 -2017024146 1579225515 -626617701 -1456
|
||||
(make-pointer 3561444187) 395687791 1968033632506257320 -1847773261
|
||||
48853 142937735275669133 -17974.0 (make-pointer 2791749948) -14140.0
|
||||
2707 3691328585 3306.0 1132012981 303633191773289330
|
||||
(make-pointer 981183954) 9114.0d0 8664374572369470 -19013.0d0
|
||||
-10288.0d0 -3679345119891954339 (make-pointer 3538786709) 23761
|
||||
-154264605 (make-pointer 2694396308) 7023 997.0d0 1009561368 241
|
||||
(make-pointer 2612292671) 48 1431872408 -32675.0d0
|
||||
(make-pointer 1587599336) 958916472 -9857.0d0 111 -14370.0d0 -7308
|
||||
-967514912 488790941 2146978095 -24111.0d0 13711 86681861 717987770
|
||||
111 1013402998690933877 17234.0d0 -8772.0 3959216275 -8711
|
||||
(make-pointer 3142780851) 9480.0 -3820453146461186120 1616574376
|
||||
-3336232268263990050 -1906114671562979758 -27925.0d0 9695970875869913114
|
||||
27033.0d0 1096518219 -12 104 3392025403 -27911 60 89 509297051
|
||||
-533066551 29158.0 110 54 -9802.0d0 593950442165910888 -79)
|
||||
7758614658402721936))
|
||||
|
||||
;;; regression test: defining an undefined foreign function should only
|
||||
;;; throw some sort of warning, not signal an error.
|
||||
|
||||
#+(or cmucl (and sbcl (or (not linkage-table) win32)))
|
||||
(pushnew 'defcfun.undefined rt::*expected-failures*)
|
||||
|
||||
(deftest defcfun.undefined
|
||||
(progn
|
||||
(eval '(defcfun ("undefined_foreign_function" undefined-foreign-function) :void))
|
||||
(compile 'undefined-foreign-function)
|
||||
t)
|
||||
t)
|
||||
|
||||
;;; Test whether all doubles are passed correctly. On some platforms, eg.
|
||||
;;; darwin/ppc, some are passed on registers others on the stack.
|
||||
(defcfun "sum_double26" :double
|
||||
(a1 :double) (a2 :double) (a3 :double) (a4 :double) (a5 :double)
|
||||
(a6 :double) (a7 :double) (a8 :double) (a9 :double) (a10 :double)
|
||||
(a11 :double) (a12 :double) (a13 :double) (a14 :double) (a15 :double)
|
||||
(a16 :double) (a17 :double) (a18 :double) (a19 :double) (a20 :double)
|
||||
(a21 :double) (a22 :double) (a23 :double) (a24 :double) (a25 :double)
|
||||
(a26 :double))
|
||||
|
||||
(deftest defcfun.double26
|
||||
(sum-double26 3.14d0 3.14d0 3.14d0 3.14d0 3.14d0 3.14d0 3.14d0
|
||||
3.14d0 3.14d0 3.14d0 3.14d0 3.14d0 3.14d0 3.14d0
|
||||
3.14d0 3.14d0 3.14d0 3.14d0 3.14d0 3.14d0 3.14d0
|
||||
3.14d0 3.14d0 3.14d0 3.14d0 3.14d0)
|
||||
81.64d0)
|
||||
|
||||
;;; Same as above for floats.
|
||||
(defcfun "sum_float26" :float
|
||||
(a1 :float) (a2 :float) (a3 :float) (a4 :float) (a5 :float)
|
||||
(a6 :float) (a7 :float) (a8 :float) (a9 :float) (a10 :float)
|
||||
(a11 :float) (a12 :float) (a13 :float) (a14 :float) (a15 :float)
|
||||
(a16 :float) (a17 :float) (a18 :float) (a19 :float) (a20 :float)
|
||||
(a21 :float) (a22 :float) (a23 :float) (a24 :float) (a25 :float)
|
||||
(a26 :float))
|
||||
|
||||
(deftest defcfun.float26
|
||||
(sum-float26 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0
|
||||
5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0)
|
||||
130.0)
|
||||
|
||||
;;;# Namespaces
|
||||
|
||||
#-cffi-sys::flat-namespace
|
||||
(progn
|
||||
(defcfun ("ns_function" ns-fun1 :library libtest) :boolean)
|
||||
(defcfun ("ns_function" ns-fun2 :library libtest2) :boolean)
|
||||
|
||||
(deftest defcfun.namespace.1
|
||||
(values (ns-fun1) (ns-fun2))
|
||||
t nil))
|
||||
|
||||
;;;# stdcall
|
||||
|
||||
#+(and x86 windows (not cffi-sys::no-stdcall))
|
||||
(progn
|
||||
(defcfun ("stdcall_fun@12" stdcall-fun :convention :stdcall) :int
|
||||
(a :int)
|
||||
(b :int)
|
||||
(c :int))
|
||||
|
||||
(deftest defcfun.stdcall.1
|
||||
(loop repeat 100 do (stdcall-fun 1 2 3)
|
||||
finally (return (stdcall-fun 1 2 3)))
|
||||
6))
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; enum.lisp --- Tests on C enums.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(defctype numeros-base-type :int)
|
||||
|
||||
(defcenum (numeros numeros-base-type)
|
||||
(:one 1)
|
||||
:two
|
||||
:three
|
||||
:four
|
||||
(:forty-one 41)
|
||||
:forty-two)
|
||||
|
||||
(defcfun "check_enums" :int
|
||||
(%one numeros)
|
||||
(%two numeros)
|
||||
(%three numeros)
|
||||
(%four numeros)
|
||||
(%forty-one numeros)
|
||||
(%forty-two numeros))
|
||||
|
||||
(deftest enum.1
|
||||
(check-enums :one :two :three 4 :forty-one :forty-two)
|
||||
1)
|
||||
|
||||
(defcenum another-boolean :false :true)
|
||||
(defcfun "return_enum" another-boolean (x :uint))
|
||||
|
||||
(deftest enum.2
|
||||
(and (eq :false (return-enum 0))
|
||||
(eq :true (return-enum 1)))
|
||||
t)
|
||||
|
||||
(defctype yet-another-boolean another-boolean)
|
||||
(defcfun ("return_enum" return-enum2) yet-another-boolean
|
||||
(x yet-another-boolean))
|
||||
|
||||
(deftest enum.3
|
||||
(and (eq :false (return-enum2 :false))
|
||||
(eq :true (return-enum2 :true)))
|
||||
t)
|
||||
|
||||
(defctype numeros-typedef numeros)
|
||||
|
||||
(deftest enum.typedef.1
|
||||
(eq (foreign-enum-keyword 'numeros-typedef 1)
|
||||
(foreign-enum-keyword 'numeros 1))
|
||||
t)
|
||||
|
||||
(deftest enum.typedef.2
|
||||
(eql (foreign-enum-value 'numeros-typedef :four)
|
||||
(foreign-enum-value 'numeros :four))
|
||||
t)
|
||||
|
||||
(defcenum enum-size.int
|
||||
(:one 1)
|
||||
(enum-size-int #.(1- (expt 2 (1- (* (foreign-type-size :unsigned-int) 8)))))
|
||||
(enum-size-negative-int #.(- (1- (expt 2 (1- (* (foreign-type-size :unsigned-int) 8))))))
|
||||
(:two 2))
|
||||
|
||||
(defcenum enum-size.uint
|
||||
(:one 1)
|
||||
(enum-size-uint #.(1- (expt 2 (* (foreign-type-size :unsigned-int) 8))))
|
||||
(:two 2))
|
||||
|
||||
(deftest enum.size
|
||||
(mapcar (alexandria:compose 'cffi::unparse-type
|
||||
'cffi::actual-type
|
||||
'cffi::parse-type)
|
||||
(list 'enum-size.int
|
||||
'enum-size.uint))
|
||||
;; The C standard only has weak constraints on the size of integer types, so
|
||||
;; we cannot really test more than one type in a platform independent way due
|
||||
;; to the possible overlaps.
|
||||
(:int
|
||||
:unsigned-int))
|
||||
|
||||
(deftest enum.size.members
|
||||
(mapcar (alexandria:conjoin 'boundp 'constantp)
|
||||
'(enum-size-int enum-size-negative-int enum-size-uint))
|
||||
(t t t))
|
||||
|
||||
(deftest enum.size.error-when-too-large
|
||||
(expecting-error
|
||||
(eval '(defcenum enum-size-too-large
|
||||
(:too-long #.(expt 2 129)))))
|
||||
:error)
|
||||
|
||||
;; There are some projects that use non-integer base type. It's not in
|
||||
;; adherence with the C standard, but we also don't lose much by
|
||||
;; allowing it.
|
||||
(defcenum (enum.double :double)
|
||||
(:one 1)
|
||||
(:two 2d0)
|
||||
(:three 3.42)
|
||||
:four)
|
||||
|
||||
(deftest enum.double
|
||||
(values-list
|
||||
(mapcar (alexandria:curry 'foreign-enum-value 'enum.double)
|
||||
'(:one :two :three :four)))
|
||||
1
|
||||
2.0d0
|
||||
3.42
|
||||
4.42)
|
||||
|
||||
;;;# Bitfield tests
|
||||
|
||||
;;; Regression test: defbitfield was misbehaving when the first value
|
||||
;;; was provided.
|
||||
(deftest bitfield.1
|
||||
(eval '(defbitfield (bf1 :long)
|
||||
(:foo 0)))
|
||||
bf1)
|
||||
|
||||
(defbitfield bf2
|
||||
one
|
||||
two
|
||||
four
|
||||
eight
|
||||
sixteen
|
||||
(bf2.outlier 42)
|
||||
thirty-two
|
||||
sixty-four)
|
||||
|
||||
(deftest bitfield.2
|
||||
(mapcar (lambda (symbol)
|
||||
(foreign-bitfield-value 'bf2 (list symbol)))
|
||||
'(one two four eight sixteen thirty-two sixty-four))
|
||||
(1 2 4 8 16 32 64))
|
||||
|
||||
(deftest bitfield.2.outlier
|
||||
(mapcar (lambda (symbol)
|
||||
(foreign-bitfield-value 'bf2 (list symbol)))
|
||||
'(one two four eight sixteen thirty-two sixty-four))
|
||||
(1 2 4 8 16 32 64))
|
||||
|
||||
(defbitfield (bf3 :int)
|
||||
(three 3)
|
||||
one
|
||||
(seven 7)
|
||||
two
|
||||
(eight 8)
|
||||
sixteen)
|
||||
|
||||
;;; Non-single-bit numbers must not influence the progression of
|
||||
;;; implicit values. Single bits larger than any before *must*
|
||||
;;; influence said progression.
|
||||
(deftest bitfield.3
|
||||
(mapcar (lambda (symbol)
|
||||
(foreign-bitfield-value 'bf3 (list symbol)))
|
||||
'(one two sixteen))
|
||||
(1 2 16))
|
||||
|
||||
(defbitfield bf4
|
||||
;; zero will be a simple enum member because it's not a valid mask
|
||||
(zero 0)
|
||||
one
|
||||
two
|
||||
four
|
||||
(three 3)
|
||||
(sixteen 16))
|
||||
|
||||
;;; Yet another edge case with the 0...
|
||||
(deftest bitfield.4
|
||||
;; These should macroexpand to the literals in Slime
|
||||
;; due to the compiler macros. Same below.
|
||||
(values (foreign-bitfield-value 'bf4 ())
|
||||
(foreign-bitfield-value 'bf4 'one)
|
||||
(foreign-bitfield-value 'bf4 '(one two))
|
||||
(foreign-bitfield-value 'bf4 '(three)) ; or should it signal an error?
|
||||
(foreign-bitfield-value 'bf4 '(sixteen)))
|
||||
0
|
||||
1
|
||||
3
|
||||
3
|
||||
16)
|
||||
|
||||
(deftest bitfield.4b
|
||||
(values (foreign-bitfield-symbols 'bf4 0)
|
||||
(foreign-bitfield-symbols 'bf4 1)
|
||||
(foreign-bitfield-symbols 'bf4 3)
|
||||
(foreign-bitfield-symbols 'bf4 8)
|
||||
(foreign-bitfield-symbols 'bf4 16))
|
||||
nil
|
||||
(one)
|
||||
(one two)
|
||||
nil
|
||||
(sixteen))
|
||||
|
||||
(deftest bitfield.translators
|
||||
(with-foreign-object (bf 'bf4 2)
|
||||
(setf (mem-aref bf 'bf4 0) 1)
|
||||
(setf (mem-aref bf 'bf4 1) 3)
|
||||
(values (mem-aref bf 'bf4 0)
|
||||
(mem-aref bf 'bf4 1)))
|
||||
(one)
|
||||
(one two))
|
||||
|
||||
#+nil
|
||||
(deftest bitfield.base-type-error
|
||||
(expecting-error
|
||||
(eval '(defbitfield (bf1 :float)
|
||||
(:foo 0))))
|
||||
:error)
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; foreign-globals.lisp --- Tests on foreign globals.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2007, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(defcvar ("var_char" *char-var*) :char)
|
||||
(defcvar "var_unsigned_char" :unsigned-char)
|
||||
(defcvar "var_short" :short)
|
||||
(defcvar "var_unsigned_short" :unsigned-short)
|
||||
(defcvar "var_int" :int)
|
||||
(defcvar "var_unsigned_int" :unsigned-int)
|
||||
(defcvar "var_long" :long)
|
||||
(defcvar "var_unsigned_long" :unsigned-long)
|
||||
(defcvar "var_float" :float)
|
||||
(defcvar "var_double" :double)
|
||||
(defcvar "var_pointer" :pointer)
|
||||
(defcvar "var_string" :string)
|
||||
(defcvar "var_long_long" :long-long)
|
||||
(defcvar "var_unsigned_long_long" :unsigned-long-long)
|
||||
|
||||
;;; The expected failures marked below result from this odd behaviour:
|
||||
;;;
|
||||
;;; (foreign-symbol-pointer "var_char") => NIL
|
||||
;;;
|
||||
;;; (foreign-symbol-pointer "var_char" :library 'libtest)
|
||||
;;; => #<Pointer to type :VOID = #xF7F50740>
|
||||
;;;
|
||||
;;; Why is this happening? --luis
|
||||
#+lispworks
|
||||
(mapc (lambda (x) (pushnew x rtest::*expected-failures*))
|
||||
'(foreign-globals.ref.char foreign-globals.get-var-pointer.1
|
||||
foreign-globals.get-var-pointer.2 foreign-globals.symbol-name
|
||||
foreign-globals.read-only.1 ))
|
||||
|
||||
(deftest foreign-globals.ref.char
|
||||
*char-var*
|
||||
-127)
|
||||
|
||||
(deftest foreign-globals.ref.unsigned-char
|
||||
*var-unsigned-char*
|
||||
255)
|
||||
|
||||
(deftest foreign-globals.ref.short
|
||||
*var-short*
|
||||
-32767)
|
||||
|
||||
(deftest foreign-globals.ref.unsigned-short
|
||||
*var-unsigned-short*
|
||||
65535)
|
||||
|
||||
(deftest foreign-globals.ref.int
|
||||
*var-int*
|
||||
-32767)
|
||||
|
||||
(deftest foreign-globals.ref.unsigned-int
|
||||
*var-unsigned-int*
|
||||
65535)
|
||||
|
||||
(deftest foreign-globals.ref.long
|
||||
*var-long*
|
||||
-2147483647)
|
||||
|
||||
(deftest foreign-globals.ref.unsigned-long
|
||||
*var-unsigned-long*
|
||||
4294967295)
|
||||
|
||||
(deftest foreign-globals.ref.float
|
||||
*var-float*
|
||||
42.0)
|
||||
|
||||
(deftest foreign-globals.ref.double
|
||||
*var-double*
|
||||
42.0d0)
|
||||
|
||||
(deftest foreign-globals.ref.pointer
|
||||
(null-pointer-p *var-pointer*)
|
||||
t)
|
||||
|
||||
(deftest foreign-globals.ref.string
|
||||
*var-string*
|
||||
"Hello, foreign world!")
|
||||
|
||||
#+openmcl (push 'foreign-globals.set.long-long rt::*expected-failures*)
|
||||
|
||||
(deftest foreign-globals.ref.long-long
|
||||
*var-long-long*
|
||||
-9223372036854775807)
|
||||
|
||||
(deftest foreign-globals.ref.unsigned-long-long
|
||||
*var-unsigned-long-long*
|
||||
18446744073709551615)
|
||||
|
||||
;; The *.set.* tests restore the old values so that the *.ref.*
|
||||
;; don't fail when re-run.
|
||||
(defmacro with-old-value-restored ((place) &body body)
|
||||
(let ((old (gensym)))
|
||||
`(let ((,old ,place))
|
||||
(prog1
|
||||
(progn ,@body)
|
||||
(setq ,place ,old)))))
|
||||
|
||||
(deftest foreign-globals.set.int
|
||||
(with-old-value-restored (*var-int*)
|
||||
(setq *var-int* 42)
|
||||
*var-int*)
|
||||
42)
|
||||
|
||||
(deftest foreign-globals.set.string
|
||||
(with-old-value-restored (*var-string*)
|
||||
(setq *var-string* "Ehxosxangxo")
|
||||
(prog1
|
||||
*var-string*
|
||||
;; free the string we just allocated
|
||||
(foreign-free (mem-ref (get-var-pointer '*var-string*) :pointer))))
|
||||
"Ehxosxangxo")
|
||||
|
||||
(deftest foreign-globals.set.long-long
|
||||
(with-old-value-restored (*var-long-long*)
|
||||
(setq *var-long-long* -9223000000000005808)
|
||||
*var-long-long*)
|
||||
-9223000000000005808)
|
||||
|
||||
(deftest foreign-globals.get-var-pointer.1
|
||||
(pointerp (get-var-pointer '*char-var*))
|
||||
t)
|
||||
|
||||
(deftest foreign-globals.get-var-pointer.2
|
||||
(mem-ref (get-var-pointer '*char-var*) :char)
|
||||
-127)
|
||||
|
||||
;;; Symbol case.
|
||||
|
||||
(defcvar "UPPERCASEINT1" :int)
|
||||
(defcvar "UPPER_CASE_INT1" :int)
|
||||
(defcvar "MiXeDCaSeInT1" :int)
|
||||
(defcvar "MiXeD_CaSe_InT1" :int)
|
||||
|
||||
(deftest foreign-globals.ref.uppercaseint1
|
||||
*uppercaseint1*
|
||||
12345)
|
||||
|
||||
(deftest foreign-globals.ref.upper-case-int1
|
||||
*upper-case-int1*
|
||||
23456)
|
||||
|
||||
(deftest foreign-globals.ref.mixedcaseint1
|
||||
*mixedcaseint1*
|
||||
34567)
|
||||
|
||||
(deftest foreign-globals.ref.mixed-case-int1
|
||||
*mixed-case-int1*
|
||||
45678)
|
||||
|
||||
(when (string= (symbol-name 'nil) "NIL")
|
||||
(let ((*readtable* (copy-readtable)))
|
||||
(setf (readtable-case *readtable*) :invert)
|
||||
(eval (read-from-string "(defcvar \"UPPERCASEINT2\" :int)"))
|
||||
(eval (read-from-string "(defcvar \"UPPER_CASE_INT2\" :int)"))
|
||||
(eval (read-from-string "(defcvar \"MiXeDCaSeInT2\" :int)"))
|
||||
(eval (read-from-string "(defcvar \"MiXeD_CaSe_InT2\" :int)"))
|
||||
(setf (readtable-case *readtable*) :preserve)
|
||||
(eval (read-from-string "(DEFCVAR \"UPPERCASEINT3\" :INT)"))
|
||||
(eval (read-from-string "(DEFCVAR \"UPPER_CASE_INT3\" :INT)"))
|
||||
(eval (read-from-string "(DEFCVAR \"MiXeDCaSeInT3\" :INT)"))
|
||||
(eval (read-from-string "(DEFCVAR \"MiXeD_CaSe_InT3\" :INT)"))))
|
||||
|
||||
|
||||
;;; EVAL gets rid of SBCL's unreachable code warnings.
|
||||
(when (string= (symbol-name (eval nil)) "nil")
|
||||
(let ((*readtable* (copy-readtable)))
|
||||
(setf (readtable-case *readtable*) :invert)
|
||||
(eval (read-from-string "(DEFCVAR \"UPPERCASEINT2\" :INT)"))
|
||||
(eval (read-from-string "(DEFCVAR \"UPPER_CASE_INT2\" :INT)"))
|
||||
(eval (read-from-string "(DEFCVAR \"MiXeDCaSeInT2\" :INT)"))
|
||||
(eval (read-from-string "(DEFCVAR \"MiXeD_CaSe_InT2\" :INT)"))
|
||||
(setf (readtable-case *readtable*) :downcase)
|
||||
(eval (read-from-string "(defcvar \"UPPERCASEINT3\" :int)"))
|
||||
(eval (read-from-string "(defcvar \"UPPER_CASE_INT3\" :int)"))
|
||||
(eval (read-from-string "(defcvar \"MiXeDCaSeInT3\" :int)"))
|
||||
(eval (read-from-string "(defcvar \"MiXeD_CaSe_InT3\" :int)"))))
|
||||
|
||||
(deftest foreign-globals.ref.uppercaseint2
|
||||
*uppercaseint2*
|
||||
12345)
|
||||
|
||||
(deftest foreign-globals.ref.upper-case-int2
|
||||
*upper-case-int2*
|
||||
23456)
|
||||
|
||||
(deftest foreign-globals.ref.mixedcaseint2
|
||||
*mixedcaseint2*
|
||||
34567)
|
||||
|
||||
(deftest foreign-globals.ref.mixed-case-int2
|
||||
*mixed-case-int2*
|
||||
45678)
|
||||
|
||||
(deftest foreign-globals.ref.uppercaseint3
|
||||
*uppercaseint3*
|
||||
12345)
|
||||
|
||||
(deftest foreign-globals.ref.upper-case-int3
|
||||
*upper-case-int3*
|
||||
23456)
|
||||
|
||||
(deftest foreign-globals.ref.mixedcaseint3
|
||||
*mixedcaseint3*
|
||||
34567)
|
||||
|
||||
(deftest foreign-globals.ref.mixed-case-int3
|
||||
*mixed-case-int3*
|
||||
45678)
|
||||
|
||||
;;; regression test:
|
||||
;;; gracefully accept symbols in defcvar
|
||||
|
||||
(defcvar *var-char* :char)
|
||||
(defcvar var-char :char)
|
||||
|
||||
(deftest foreign-globals.symbol-name
|
||||
(values *var-char* var-char)
|
||||
-127 -127)
|
||||
|
||||
;;;# Namespace
|
||||
|
||||
#-cffi-sys::flat-namespace
|
||||
(progn
|
||||
(deftest foreign-globals.namespace.1
|
||||
(values
|
||||
(mem-ref (foreign-symbol-pointer "var_char" :library 'libtest) :char)
|
||||
(foreign-symbol-pointer "var_char" :library 'libtest2))
|
||||
-127 nil)
|
||||
|
||||
(deftest foreign-globals.namespace.2
|
||||
(values
|
||||
(mem-ref (foreign-symbol-pointer "ns_var" :library 'libtest) :boolean)
|
||||
(mem-ref (foreign-symbol-pointer "ns_var" :library 'libtest2) :boolean))
|
||||
t nil)
|
||||
|
||||
;; For its "default" module, Lispworks seems to cache lookups from
|
||||
;; the newest module tried. If a lookup happens to have failed
|
||||
;; subsequent lookups will fail even the symbol exists in other
|
||||
;; modules. So this test fails.
|
||||
#+lispworks
|
||||
(pushnew 'foreign-globals.namespace.3 regression-test::*expected-failures*)
|
||||
|
||||
(deftest foreign-globals.namespace.3
|
||||
(values
|
||||
(foreign-symbol-pointer "var_char" :library 'libtest2)
|
||||
(mem-ref (foreign-symbol-pointer "var_char") :char))
|
||||
nil -127)
|
||||
|
||||
(defcvar ("ns_var" *ns-var1* :library libtest) :boolean)
|
||||
(defcvar ("ns_var" *ns-var2* :library libtest2) :boolean)
|
||||
|
||||
(deftest foreign-globals.namespace.4
|
||||
(values *ns-var1* *ns-var2*)
|
||||
t nil))
|
||||
|
||||
;;;# Read-only
|
||||
|
||||
(defcvar ("var_char" *var-char-ro* :read-only t) :char
|
||||
"docstring")
|
||||
|
||||
(deftest foreign-globals.read-only.1
|
||||
(values *var-char-ro*
|
||||
(ignore-errors (setf *var-char-ro* 12)))
|
||||
-127 nil)
|
||||
|
||||
(deftest defcvar.docstring
|
||||
(documentation '*var-char-ro* 'variable)
|
||||
"docstring")
|
||||
|
||||
;;;# Other tests
|
||||
|
||||
;;; RT: FOREIGN-SYMBOL-POINTER shouldn't signal an error when passed
|
||||
;;; an undefined variable.
|
||||
(deftest foreign-globals.undefined.1
|
||||
(foreign-symbol-pointer "surely-undefined?")
|
||||
nil)
|
||||
|
||||
(deftest foreign-globals.error.1
|
||||
(handler-case (foreign-symbol-pointer 'not-a-string)
|
||||
(type-error () t))
|
||||
t)
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; fsbv.lisp --- Tests of foreign structure by value calls.
|
||||
;;;
|
||||
;;; Copyright (C) 2011, Liam M. Healy
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
;; Requires struct.lisp
|
||||
|
||||
(defcfun "sumpair" :int
|
||||
(p (:struct struct-pair)))
|
||||
|
||||
(defcfun "makepair" (:struct struct-pair)
|
||||
(condition :bool))
|
||||
|
||||
(defcfun "doublepair" (:struct struct-pair)
|
||||
(p (:struct struct-pair)))
|
||||
|
||||
(defcfun "prodsumpair" :double
|
||||
(p (:struct struct-pair+double)))
|
||||
|
||||
(defcfun "doublepairdouble" (:struct struct-pair+double)
|
||||
(p (:struct struct-pair+double)))
|
||||
|
||||
;;; Call struct by value
|
||||
(deftest fsbv.1
|
||||
(sumpair '(1 . 2))
|
||||
3)
|
||||
|
||||
;;; See lp#1528719
|
||||
(deftest (fsbv.wfo :expected-to-fail t)
|
||||
(with-foreign-object (arg '(:struct struct-pair))
|
||||
(convert-into-foreign-memory '(40 . 2) '(:struct struct-pair) arg)
|
||||
(sumpair arg))
|
||||
42)
|
||||
|
||||
;;; Call and return struct by value
|
||||
(deftest fsbv.2
|
||||
(doublepair '(1 . 2))
|
||||
(2 . 4))
|
||||
|
||||
;;; return struct by value
|
||||
(deftest (fsbv.makepair.1 :expected-to-fail t)
|
||||
(makepair nil)
|
||||
(-127 . 43))
|
||||
|
||||
(deftest (fsbv.makepair.2 :expected-to-fail t)
|
||||
(makepair t)
|
||||
(-127 . 42))
|
||||
|
||||
;;; Call recursive structure by value
|
||||
(deftest fsbv.3
|
||||
(prodsumpair '(pr (a 4 b 5) dbl 2.5d0))
|
||||
22.5d0)
|
||||
|
||||
;;; Call and return recursive structure by value
|
||||
(deftest fsbv.4
|
||||
(let ((ans (doublepairdouble '(pr (a 4 b 5) dbl 2.5d0))))
|
||||
(values (getf (getf ans 'pr) 'a)
|
||||
(getf (getf ans 'pr) 'b)
|
||||
(getf ans 'dbl)))
|
||||
8
|
||||
10
|
||||
5.0d0)
|
||||
|
||||
(defcstruct (struct-with-array :size 6)
|
||||
(s1 (:array :char 6)))
|
||||
|
||||
(defcfun "zork" :void
|
||||
(p (:struct struct-with-array)))
|
||||
|
||||
;;; Typedef fsbv test
|
||||
|
||||
(defcfun ("sumpair" sumpair2) :int
|
||||
(p struct-pair-typedef1))
|
||||
|
||||
(deftest fsbv.5
|
||||
(sumpair2 '(1 . 2))
|
||||
3)
|
||||
|
||||
(defcfun "returnpairpointer" (:pointer (:struct struct-pair))
|
||||
(ignored (:struct struct-pair)))
|
||||
|
||||
(deftest fsbv.return-a-pointer
|
||||
(let ((ptr (returnpairpointer '(1 . 2))))
|
||||
(+ (foreign-slot-value ptr '(:struct struct-pair) 'a)
|
||||
(foreign-slot-value ptr '(:struct struct-pair) 'b)))
|
||||
42)
|
||||
|
||||
;;; Test ulonglong on no-long-long implementations.
|
||||
|
||||
(defcfun "ullsum" :unsigned-long-long
|
||||
(a :unsigned-long-long) (b :unsigned-long-long))
|
||||
|
||||
(deftest fsbv.6
|
||||
(ullsum #x10DEADBEEF #x2300000000)
|
||||
#x33DEADBEEF)
|
||||
|
||||
;;; Combine structures by value with a string argument
|
||||
(defcfun "stringlenpair" (:struct struct-pair)
|
||||
(s :string)
|
||||
(p (:struct struct-pair)))
|
||||
|
||||
(deftest fsbv.7
|
||||
(stringlenpair "abc" '(1 . 2))
|
||||
(3 . 6))
|
||||
|
||||
;;; Combine structures by value with an enum argument
|
||||
(defcfun "enumpair" (:int)
|
||||
(e numeros)
|
||||
(p (:struct struct-pair)))
|
||||
|
||||
(deftest fsbv.8
|
||||
(enumpair :two '(1 . 2))
|
||||
5)
|
||||
|
||||
;;; returning struct with bitfield member (bug #1474631)
|
||||
(defbitfield (struct-bitfield :unsigned-int)
|
||||
(:a 1)
|
||||
(:b 2))
|
||||
|
||||
(defcstruct bitfield-struct
|
||||
(b struct-bitfield))
|
||||
|
||||
(defcfun "structbitfield" (:struct bitfield-struct)
|
||||
(x :unsigned-int))
|
||||
|
||||
(defctype struct-bitfield-typedef struct-bitfield)
|
||||
|
||||
(defcstruct bitfield-struct.2
|
||||
(b struct-bitfield-typedef))
|
||||
|
||||
(defcfun ("structbitfield" structbitfield.2) (:struct bitfield-struct.2)
|
||||
(x :unsigned-int))
|
||||
|
||||
;; these would get stuck in an infinite loop previously
|
||||
(deftest fsbv.struct-bitfield.0
|
||||
(structbitfield 0)
|
||||
(b nil))
|
||||
|
||||
(deftest fsbv.struct-bitfield.1
|
||||
(structbitfield 1)
|
||||
(b (:a)))
|
||||
|
||||
(deftest fsbv.struct-bitfield.2
|
||||
(structbitfield 2)
|
||||
(b (:b)))
|
||||
|
||||
(deftest fsbv.struct-bitfield.3
|
||||
(structbitfield.2 2)
|
||||
(b (:b)))
|
||||
|
||||
;;; Test for a discrepancy between normal and fsbv return values
|
||||
(cffi:define-foreign-type int-return-code (cffi::foreign-type-alias)
|
||||
()
|
||||
(:default-initargs :actual-type (cffi::parse-type :int))
|
||||
(:simple-parser int-return-code))
|
||||
|
||||
(defmethod cffi:expand-from-foreign (value (type int-return-code))
|
||||
;; NOTE: strictly speaking it should be
|
||||
;; (cffi:convert-from-foreign ,value :int), but it's irrelevant in this case
|
||||
`(let ((return-code ,value))
|
||||
(check-type return-code integer)
|
||||
return-code))
|
||||
|
||||
(defcfun (noargs-with-typedef "noargs") int-return-code)
|
||||
|
||||
(deftest fsbv.noargs-with-typedef ; for reference, not an FSBV call
|
||||
(noargs-with-typedef)
|
||||
42)
|
||||
|
||||
(defcfun (sumpair-with-typedef "sumpair") int-return-code
|
||||
(p (:struct struct-pair)))
|
||||
|
||||
(deftest (fsbv.return-value-typedef)
|
||||
(sumpair-with-typedef '(40 . 2))
|
||||
42)
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; funcall.lisp --- Tests function calling.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, James Bielman <jamesjb@jamesjb.com>
|
||||
;;; Copyright (C) 2005-2007, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
;;;# Calling with Built-In C Types
|
||||
;;;
|
||||
;;; Tests calling standard C library functions both passing and
|
||||
;;; returning each built-in type.
|
||||
|
||||
;;; Don't run these tests if the implementation does not support
|
||||
;;; foreign-funcall.
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(progn
|
||||
|
||||
(deftest funcall.char
|
||||
(foreign-funcall "toupper" :char (char-code #\a) :char)
|
||||
#.(char-code #\A))
|
||||
|
||||
(deftest funcall.int.1
|
||||
(foreign-funcall "abs" :int -100 :int)
|
||||
100)
|
||||
|
||||
(defun funcall-abs (n)
|
||||
(foreign-funcall "abs" :int n :int))
|
||||
|
||||
;;; regression test: lispworks's %foreign-funcall based on creating
|
||||
;;; and caching foreign-funcallables at macro-expansion time.
|
||||
(deftest funcall.int.2
|
||||
(funcall-abs -42)
|
||||
42)
|
||||
|
||||
(deftest funcall.long
|
||||
(foreign-funcall "labs" :long -131072 :long)
|
||||
131072)
|
||||
|
||||
#-cffi-sys::no-long-long
|
||||
(deftest funcall.long-long
|
||||
(foreign-funcall "my_llabs" :long-long -9223372036854775807 :long-long)
|
||||
9223372036854775807)
|
||||
|
||||
#-cffi-sys::no-long-long
|
||||
(deftest funcall.unsigned-long-long
|
||||
(let ((ullong-max (1- (expt 2 (* 8 (foreign-type-size :unsigned-long-long))))))
|
||||
(eql ullong-max
|
||||
(foreign-funcall "ullong" :unsigned-long-long ullong-max
|
||||
:unsigned-long-long)))
|
||||
t)
|
||||
|
||||
(deftest funcall.float
|
||||
(foreign-funcall "my_sqrtf" :float 16.0 :float)
|
||||
4.0)
|
||||
|
||||
(deftest funcall.double
|
||||
(foreign-funcall "sqrt" :double 36.0d0 :double)
|
||||
6.0d0)
|
||||
|
||||
#+(and scl long-float)
|
||||
(deftest funcall.long-double
|
||||
(foreign-funcall "sqrtl" :long-double 36.0l0 :long-double)
|
||||
6.0l0)
|
||||
|
||||
(deftest funcall.string.1
|
||||
(foreign-funcall "strlen" :string "Hello" :int)
|
||||
5)
|
||||
|
||||
(deftest funcall.string.2
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(foreign-funcall "strcpy" :pointer s :string "Hello" :pointer)
|
||||
(foreign-funcall "strcat" :pointer s :string ", world!" :pointer))
|
||||
"Hello, world!")
|
||||
|
||||
(deftest funcall.string.3
|
||||
(with-foreign-pointer (ptr 100)
|
||||
(lisp-string-to-foreign "Hello, " ptr 8)
|
||||
(foreign-funcall "strcat" :pointer ptr :string "world!" :string))
|
||||
"Hello, world!")
|
||||
|
||||
;;;# Calling Varargs Functions
|
||||
|
||||
(deftest funcall.varargs.nostdlib
|
||||
(foreign-funcall-varargs
|
||||
"sum_double_arbitrary" (:int 26)
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0
|
||||
:double)
|
||||
81.64d0)
|
||||
|
||||
;; The CHAR argument must be passed as :INT because chars are promoted
|
||||
;; to ints when passed as variable arguments.
|
||||
(deftest funcall.varargs.char
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(foreign-funcall-varargs
|
||||
"sprintf" (:pointer s :string "%c") :int 65 :int))
|
||||
"A")
|
||||
|
||||
(deftest funcall.varargs.int
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(foreign-funcall-varargs
|
||||
"sprintf" (:pointer s :string "%d") :int 1000 :int))
|
||||
"1000")
|
||||
|
||||
(deftest funcall.varargs.long
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(foreign-funcall-varargs
|
||||
"sprintf" (:pointer s :string "%ld")
|
||||
:long 131072 :int))
|
||||
"131072")
|
||||
|
||||
;;; There is no FUNCALL.VARARGS.FLOAT as floats are promoted to double
|
||||
;;; when passed as variable arguments. Currently this fails in SBCL
|
||||
;;; and CMU CL on Darwin/ppc.
|
||||
(deftest funcall.varargs.double
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(foreign-funcall-varargs
|
||||
"sprintf" (:pointer s :string "%.2f") :double (coerce pi 'double-float) :int))
|
||||
"3.14")
|
||||
|
||||
#+(and scl long-float)
|
||||
(deftest funcall.varargs.long-double
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(foreign-funcall-varargs
|
||||
"sprintf" :pointer s :string "%.2Lf" :long-double pi :int))
|
||||
"3.14")
|
||||
|
||||
(deftest funcall.varargs.string
|
||||
(with-foreign-pointer-as-string (s 100)
|
||||
(setf (mem-ref s :char) 0)
|
||||
(foreign-funcall-varargs
|
||||
"sprintf" (:pointer s :string "%s, %s!") :string "Hello" :string "world" :int))
|
||||
"Hello, world!")
|
||||
|
||||
;;; See DEFCFUN.DOUBLE26.
|
||||
(deftest funcall.double26
|
||||
(foreign-funcall "sum_double26"
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double 3.14d0
|
||||
:double 3.14d0 :double 3.14d0 :double)
|
||||
81.64d0)
|
||||
|
||||
;;; See DEFCFUN.FLOAT26.
|
||||
(deftest funcall.float26
|
||||
(foreign-funcall "sum_float26"
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
|
||||
:float 5.0 :float)
|
||||
130.0)
|
||||
|
||||
;;; Funcalling a pointer.
|
||||
(deftest funcall.f-s-p.1
|
||||
(foreign-funcall-pointer (foreign-symbol-pointer "abs") nil :int -42 :int)
|
||||
42)
|
||||
|
||||
;;;# Namespaces
|
||||
|
||||
#-cffi-sys::flat-namespace
|
||||
(deftest funcall.namespace.1
|
||||
(values (foreign-funcall ("ns_function" :library libtest) :boolean)
|
||||
(foreign-funcall ("ns_function" :library libtest2) :boolean))
|
||||
t nil)
|
||||
|
||||
;;;# stdcall
|
||||
|
||||
#+(and x86 windows (not cffi-sys::no-stdcall))
|
||||
(deftest funcall.stdcall.1
|
||||
(flet ((fun ()
|
||||
(foreign-funcall ("stdcall_fun@12" :convention :stdcall)
|
||||
:int 1 :int 2 :int 3 :int)))
|
||||
(loop repeat 100 do (fun)
|
||||
finally (return (fun))))
|
||||
6)
|
||||
|
||||
;;; RT: NIL arguments are skipped
|
||||
|
||||
(defvar *nil-skipped*)
|
||||
|
||||
(define-foreign-type check-nil-skip-type ()
|
||||
()
|
||||
(:actual-type :pointer)
|
||||
(:simple-parser check-nil-skip-type))
|
||||
|
||||
(defmethod expand-to-foreign (val (type check-nil-skip-type))
|
||||
(declare (ignore val))
|
||||
(setf *nil-skipped* nil)
|
||||
(null-pointer))
|
||||
|
||||
(deftest funcall.nil-skip
|
||||
(let ((*nil-skipped* t))
|
||||
(compile nil '(lambda ()
|
||||
(foreign-funcall "abs" check-nil-skip-type nil)))
|
||||
*nil-skipped*)
|
||||
nil)
|
||||
|
||||
;;; RT: CLISP returns NIL instead of a null-pointer
|
||||
|
||||
(deftest funcall.pointer-not-nil
|
||||
(not (null (foreign-funcall "strchr" :string "" :int 1 :pointer)))
|
||||
t)
|
||||
|
||||
) ;; #-cffi-sys::no-foreign-funcall
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; grovel.lisp --- CFFI-Grovel tests.
|
||||
;;;
|
||||
;;; Copyright (C) 2014, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(deftest %invoke
|
||||
(cffi-grovel::invoke "echo" "test")
|
||||
nil nil 0)
|
||||
|
||||
(defun grovel-forms (forms &key (quiet t))
|
||||
(uiop:with-temporary-file (:stream grovel-stream :pathname grovel-file)
|
||||
(with-standard-io-syntax
|
||||
(with-open-stream (*standard-output* grovel-stream)
|
||||
(let ((*package* (find-package :keyword)))
|
||||
(mapc #'write forms))))
|
||||
(let ((lisp-file (let ((*debug-io* (if quiet (make-broadcast-stream) *debug-io*)))
|
||||
(cffi-grovel:process-grovel-file grovel-file))))
|
||||
(unwind-protect
|
||||
(load lisp-file)
|
||||
(uiop:delete-file-if-exists lisp-file)))))
|
||||
|
||||
(defun bug-1395242-helper (enum-type base-type constant-name)
|
||||
(check-type enum-type (member constantenum cenum))
|
||||
(check-type base-type string)
|
||||
(check-type constant-name string)
|
||||
(let ((enum-name (intern (symbol-name (gensym))))
|
||||
(base-type-name (intern (symbol-name (gensym)))))
|
||||
(grovel-forms `((ctype ,base-type-name ,base-type)
|
||||
(,enum-type (,enum-name :base-type ,base-type-name)
|
||||
((:value ,constant-name)))))
|
||||
(cffi:foreign-enum-value enum-name :value)))
|
||||
|
||||
(deftest bug-1395242
|
||||
(labels
|
||||
((process-expression (expression)
|
||||
(loop for enum-type in '(constantenum cenum)
|
||||
always (destructuring-bind (base-type &rest evaluations) expression
|
||||
(loop for (name expected-value) in evaluations
|
||||
for actual-value = (bug-1395242-helper enum-type base-type name)
|
||||
always (or (= expected-value actual-value)
|
||||
(progn
|
||||
(format *error-output*
|
||||
"Test failed for case: ~A, ~A, ~A (expected ~A, actual ~A)~%"
|
||||
enum-type base-type name expected-value actual-value)
|
||||
nil)))))))
|
||||
(every #'process-expression
|
||||
'(("uint8_t" ("UINT8_MAX" 255) ("INT8_MAX" 127) ("INT8_MIN" 128))
|
||||
("int8_t" ("INT8_MIN" -128) ("INT8_MAX" 127) ("UINT8_MAX" -1))
|
||||
("uint16_t" ("UINT16_MAX" 65535) ("INT8_MIN" 65408))
|
||||
("int16_t" ("INT16_MIN" -32768) ("INT16_MAX" 32767) ("UINT16_MAX" -1))
|
||||
("uint32_t" ("UINT32_MAX" 4294967295) ("INT8_MIN" 4294967168))
|
||||
("int32_t" ("INT32_MIN" -2147483648) ("INT32_MAX" 2147483647)))))
|
||||
t)
|
||||
|
||||
(defvar *grovelled-features*)
|
||||
|
||||
(deftest grovel-feature
|
||||
(let ((*grovelled-features* nil))
|
||||
(grovel-forms `((in-package :cffi-tests)
|
||||
(include "limits.h")
|
||||
(feature grovel-test-feature "CHAR_BIT")
|
||||
(feature :char-bit "CHAR_BIT"
|
||||
:feature-list *grovelled-features*)
|
||||
(feature :inexistent-grovel-feature
|
||||
"INEXISTENT_CFFI_GROVEL_FEATURE"
|
||||
:feature-list *grovelled-features*)))
|
||||
(unwind-protect
|
||||
(values (and (member 'grovel-test-feature *features*) t)
|
||||
(and (member :char-bit *grovelled-features*) t)
|
||||
(member :inexistent-grovel-feature *grovelled-features*))
|
||||
(alexandria:removef *features* 'grovel-test-feature)))
|
||||
t t nil)
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*-
|
||||
*
|
||||
* libfsbv.c --- auxiliary C lib for testing foreign structure by value calls
|
||||
*
|
||||
* Copyright (C) 2011, 2015 Liam M. Healy
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
/* MSVC doesn't have stdint.h and uses a different syntax for stdcall */
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _MSC_VER
|
||||
#define STDCALL __stdcall
|
||||
#else
|
||||
#define STDCALL __attribute__((stdcall))
|
||||
#endif
|
||||
#else
|
||||
#define STDCALL
|
||||
#endif
|
||||
|
||||
struct struct_pair {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct struct_pair_double {
|
||||
struct struct_pair pr;
|
||||
double dbl;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ONE = 1,
|
||||
TWO,
|
||||
THREE,
|
||||
FOUR,
|
||||
FORTY_ONE = 41,
|
||||
FORTY_TWO
|
||||
} numeros;
|
||||
|
||||
int sumpair (struct struct_pair sp);
|
||||
int enumpair (numeros mynum, struct struct_pair sp);
|
||||
struct struct_pair doublepair (struct struct_pair dp);
|
||||
double prodsumpair (struct struct_pair_double spd);
|
||||
struct struct_pair_double doublepairdouble (struct struct_pair_double pd);
|
||||
|
||||
DLLEXPORT
|
||||
int sumpair (struct struct_pair sp)
|
||||
{
|
||||
return sp.a + sp.b;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int enumpair (numeros mynum, struct struct_pair sp)
|
||||
{
|
||||
if ( mynum == ONE )
|
||||
{
|
||||
return sp.a + sp.b;
|
||||
}
|
||||
else if ( mynum == TWO )
|
||||
{
|
||||
return sp.a + 2*sp.b;
|
||||
}
|
||||
else if ( mynum == THREE )
|
||||
{
|
||||
return 2*sp.a + sp.b;
|
||||
}
|
||||
else if ( mynum == FOUR )
|
||||
{
|
||||
return 2*sp.a + 2*sp.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 41*sp.a + 42*sp.b;
|
||||
}
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct struct_pair makepair (bool cond)
|
||||
{
|
||||
struct struct_pair ret;
|
||||
ret.a = -127;
|
||||
ret.b = cond ? 42 : 43;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct struct_pair static_pair = { 40, 2};
|
||||
|
||||
DLLEXPORT
|
||||
struct struct_pair * returnpairpointer (struct struct_pair ignored)
|
||||
{
|
||||
return &static_pair;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct struct_pair doublepair (struct struct_pair dp)
|
||||
{
|
||||
struct struct_pair ret;
|
||||
ret.a = 2*dp.a;
|
||||
ret.b = 2*dp.b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
double prodsumpair (struct struct_pair_double pd)
|
||||
{
|
||||
return pd.dbl * sumpair(pd.pr);
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct struct_pair_double doublepairdouble (struct struct_pair_double pd)
|
||||
{
|
||||
struct struct_pair_double ret;
|
||||
ret.pr = doublepair(pd.pr);
|
||||
ret.dbl = 2*pd.dbl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
unsigned long long ullsum (unsigned long long a, unsigned long long b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct struct_pair stringlenpair (char *string, struct struct_pair dp)
|
||||
{
|
||||
struct struct_pair ret;
|
||||
int len = strlen(string);
|
||||
ret.a = len*dp.a;
|
||||
ret.b = len*dp.b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct bitfield_struct {
|
||||
unsigned int b;
|
||||
};
|
||||
|
||||
DLLEXPORT
|
||||
struct bitfield_struct structbitfield (unsigned int x) {
|
||||
struct bitfield_struct ret;
|
||||
ret.b = x;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,985 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*-
|
||||
*
|
||||
* libtest.c --- auxiliary C lib for testing purposes
|
||||
*
|
||||
* Copyright (C) 2005-2007, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* MSVC doesn't have stdint.h and uses a different syntax for stdcall */
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _MSC_VER
|
||||
#define STDCALL __stdcall
|
||||
#else
|
||||
#define STDCALL __attribute__((stdcall))
|
||||
#endif
|
||||
#else
|
||||
#define STDCALL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some functions that aren't available on WIN32
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
float my_sqrtf(float n)
|
||||
{
|
||||
return (float) sqrt((double) n);
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
char *my_strdup(const char *str)
|
||||
{
|
||||
char *p = malloc(strlen(str) + 1);
|
||||
strcpy(p, str);
|
||||
return p;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
void my_strfree(char *str)
|
||||
{
|
||||
free(str);
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
long long my_llabs(long long n)
|
||||
{
|
||||
return n < 0 ? -n : n;
|
||||
}
|
||||
|
||||
|
||||
DLLEXPORT
|
||||
unsigned long long ullong(unsigned long long n)
|
||||
{
|
||||
return n == ULLONG_MAX ? n : 42;
|
||||
}
|
||||
|
||||
/*
|
||||
* Foreign Globals
|
||||
*
|
||||
* (var_int is used in MISC-TYPES.EXPAND.3 as well)
|
||||
*/
|
||||
|
||||
DLLEXPORT char * dll_version = "20120107";
|
||||
|
||||
/* TODO: look into signed char vs. unsigned char issue */
|
||||
DLLEXPORT char var_char = -127;
|
||||
DLLEXPORT unsigned char var_unsigned_char = 255;
|
||||
DLLEXPORT short var_short = -32767;
|
||||
DLLEXPORT unsigned short var_unsigned_short = 65535;
|
||||
DLLEXPORT int var_int = -32767;
|
||||
DLLEXPORT unsigned int var_unsigned_int = 65535;
|
||||
DLLEXPORT long var_long = -2147483647L;
|
||||
DLLEXPORT unsigned long var_unsigned_long = 4294967295UL;
|
||||
DLLEXPORT float var_float = 42.0f;
|
||||
DLLEXPORT double var_double = 42.0;
|
||||
DLLEXPORT void * var_pointer = NULL;
|
||||
DLLEXPORT char * var_string = "Hello, foreign world!";
|
||||
|
||||
DLLEXPORT long long var_long_long = -9223372036854775807LL;
|
||||
DLLEXPORT unsigned long long var_unsigned_long_long = 18446744073709551615ULL;
|
||||
|
||||
DLLEXPORT float float_max = FLT_MAX;
|
||||
DLLEXPORT float float_min = FLT_MIN;
|
||||
DLLEXPORT double double_max = DBL_MAX;
|
||||
DLLEXPORT double double_min = DBL_MIN;
|
||||
|
||||
/*
|
||||
* Callbacks
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
int expect_char_sum(char (*f)(char, char))
|
||||
{
|
||||
return f('a', 3) == 'd';
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_unsigned_char_sum(unsigned char (*f)(unsigned char, unsigned char))
|
||||
{
|
||||
return f(UCHAR_MAX-1, 1) == UCHAR_MAX;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_short_sum(short (*f)(short a, short b))
|
||||
{
|
||||
return f(SHRT_MIN+1, -1) == SHRT_MIN;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_unsigned_short_sum(unsigned short (*f)(unsigned short,
|
||||
unsigned short))
|
||||
{
|
||||
return f(USHRT_MAX-1, 1) == USHRT_MAX;
|
||||
}
|
||||
|
||||
/* used in MISC-TYPES.EXPAND.4 as well */
|
||||
DLLEXPORT
|
||||
int expect_int_sum(int (*f)(int, int))
|
||||
{
|
||||
return f(INT_MIN+1, -1) == INT_MIN;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_unsigned_int_sum(unsigned int (*f)(unsigned int, unsigned int))
|
||||
{
|
||||
return f(UINT_MAX-1, 1) == UINT_MAX;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_long_sum(long (*f)(long, long))
|
||||
{
|
||||
return f(LONG_MIN+1, -1) == LONG_MIN;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_unsigned_long_sum(unsigned long (*f)(unsigned long, unsigned long))
|
||||
{
|
||||
return f(ULONG_MAX-1, 1) == ULONG_MAX;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_long_long_sum(long long (*f)(long long, long long))
|
||||
{
|
||||
return f(LLONG_MIN+1, -1) == LLONG_MIN;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_unsigned_long_long_sum (unsigned long long
|
||||
(*f)(unsigned long long, unsigned long long))
|
||||
{
|
||||
return f(ULLONG_MAX-1, 1) == ULLONG_MAX;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_float_sum(float (*f)(float, float))
|
||||
{
|
||||
/*printf("\n>>> FLOAT: %f <<<\n", f(20.0f, 22.0f));*/
|
||||
return f(20.0f, 22.0f) == 42.0f;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_double_sum(double (*f)(double, double))
|
||||
{
|
||||
/*printf("\n>>> DOUBLE: %f<<<\n", f(-20.0, -22.0));*/
|
||||
return f(-20.0, -22.0) == -42.0;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_long_double_sum(long double (*f)(long double, long double))
|
||||
{
|
||||
/*printf("\n>>> DOUBLE: %f<<<\n", f(-20.0, -22.0));*/
|
||||
return f(-20.0, -22.0) == -42.0;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_pointer_sum(void* (*f)(void*, int))
|
||||
{
|
||||
return f(NULL, 0xDEAD) == (void *) 0xDEAD;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int expect_strcat(char* (*f)(char*, char*))
|
||||
{
|
||||
char *ret = f("Hello, ", "C world!");
|
||||
int res = strcmp(ret, "Hello, C world!") == 0;
|
||||
/* commented out as a quick fix on platforms that don't
|
||||
foreign allocate in C malloc space. */
|
||||
/*free(ret);*/ /* is this allowed? */
|
||||
return res;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
void pass_int_ref(void (*f)(int*))
|
||||
{
|
||||
int x = 1984;
|
||||
f(&x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enums
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
ONE = 1,
|
||||
TWO,
|
||||
THREE,
|
||||
FOUR,
|
||||
FORTY_ONE = 41,
|
||||
FORTY_TWO
|
||||
} numeros;
|
||||
|
||||
DLLEXPORT
|
||||
int check_enums(numeros one, numeros two, numeros three, numeros four,
|
||||
numeros forty_one, numeros forty_two)
|
||||
{
|
||||
if (one == ONE && two == TWO && three == THREE && four == FOUR &&
|
||||
forty_one == FORTY_ONE && forty_two == FORTY_TWO)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum { FALSE, TRUE } another_boolean;
|
||||
|
||||
DLLEXPORT
|
||||
another_boolean return_enum(int x)
|
||||
{
|
||||
if (x == 0)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Booleans
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
int equalequal(int a, unsigned int b)
|
||||
{
|
||||
return ((unsigned int) a) == b;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
char bool_and(unsigned char a, char b)
|
||||
{
|
||||
return a && b;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
unsigned long bool_xor(long a, unsigned long b)
|
||||
{
|
||||
return (a && !b) || (!a && b);
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
unsigned sizeof_bool(void)
|
||||
{
|
||||
return (unsigned) sizeof(_Bool);
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
unsigned bool_to_unsigned(_Bool b)
|
||||
{
|
||||
return (unsigned) b;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
_Bool unsigned_to_bool(unsigned u)
|
||||
{
|
||||
return (_Bool) u;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test struct alignment issues. These comments assume the x86 gABI.
|
||||
* Hopefully these tests will spot alignment issues in others archs
|
||||
* too.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.1
|
||||
*/
|
||||
|
||||
struct s_ch {
|
||||
char a_char;
|
||||
};
|
||||
|
||||
/* This struct's size should be 2 bytes */
|
||||
struct s_s_ch {
|
||||
char another_char;
|
||||
struct s_ch a_s_ch;
|
||||
};
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_ch the_s_s_ch = { 2, { 1 } };
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.2
|
||||
*/
|
||||
|
||||
/* This one should be alignment should be the same as short's alignment. */
|
||||
struct s_short {
|
||||
char a_char;
|
||||
char another_char;
|
||||
short a_short;
|
||||
};
|
||||
|
||||
struct s_s_short {
|
||||
char yet_another_char;
|
||||
struct s_short a_s_short; /* so this should be 2-byte aligned */
|
||||
}; /* size: 6 bytes */
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_short the_s_s_short = { 4, { 1, 2, 3 } };
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.3
|
||||
*/
|
||||
|
||||
/* This test will, among other things, check for the existence tail padding. */
|
||||
|
||||
struct s_double {
|
||||
char a_char; /* 1 byte */
|
||||
/* padding: 3 bytes */
|
||||
double a_double; /* 8 bytes */
|
||||
char another_char; /* 1 byte */
|
||||
/* padding: 3 bytes */
|
||||
}; /* total size: 16 bytes */
|
||||
|
||||
struct s_s_double {
|
||||
char yet_another_char; /* 1 byte */
|
||||
/* 3 bytes padding */
|
||||
struct s_double a_s_double; /* 16 bytes */
|
||||
short a_short; /* 2 byte */
|
||||
/* 2 bytes padding */
|
||||
}; /* total size: 24 bytes */
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_double the_s_s_double = { 4, { 1, 2.0, 3 }, 5 };
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.4
|
||||
*/
|
||||
struct s_s_s_double {
|
||||
short another_short; /* 2 bytes */
|
||||
/* 2 bytes padding */
|
||||
struct s_s_double a_s_s_double; /* 24 bytes */
|
||||
char last_char; /* 1 byte */
|
||||
/* 3 bytes padding */
|
||||
}; /* total size: 32 */
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_s_double the_s_s_s_double = { 6, { 4, { 1, 2.0, 3 }, 5 }, 7 };
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.5
|
||||
*/
|
||||
|
||||
/* MacOSX ABI says: "The embedding alignment of the first element in a data
|
||||
structure is equal to the element's natural alignment." and "For subsequent
|
||||
elements that have a natural alignment greater than 4 bytes, the embedding
|
||||
alignment is 4, unless the element is a vector." */
|
||||
|
||||
/* note: these rules will apply to the structure itself. So, unless it is
|
||||
the first element of another structure, its alignment will be 4. */
|
||||
|
||||
/* the following offsets and sizes are specific to darwin/ppc32 */
|
||||
|
||||
struct s_double2 {
|
||||
double a_double; /* 8 bytes (alignment 8) */
|
||||
short a_short; /* 2 bytes */
|
||||
/* 6 bytes padding */
|
||||
}; /* total size: 16 */
|
||||
|
||||
struct s_s_double2 {
|
||||
char a_char; /* 1 byte */
|
||||
/* 3 bytes padding */
|
||||
struct s_double2 a_s_double2; /* 16 bytes, alignment 4 */
|
||||
short another_short; /* 2 bytes */
|
||||
/* 2 bytes padding */
|
||||
}; /* total size: 24 bytes */
|
||||
/* alignment: 4 */
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_double2 the_s_s_double2 = { 3, { 1.0, 2 }, 4 };
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.6
|
||||
*/
|
||||
|
||||
/* Same as STRUCT.ALIGNMENT.5 but with long long. */
|
||||
|
||||
struct s_long_long {
|
||||
long long a_long_long; /* 8 bytes (alignment 8) */
|
||||
short a_short; /* 2 bytes */
|
||||
/* 6 bytes padding */
|
||||
}; /* total size: 16 */
|
||||
|
||||
struct s_s_long_long {
|
||||
char a_char; /* 1 byte */
|
||||
/* 3 bytes padding */
|
||||
struct s_long_long a_s_long_long; /* 16 bytes, alignment 4 */
|
||||
short a_short; /* 2 bytes */
|
||||
/* 2 bytes padding */
|
||||
}; /* total size: 24 bytes */
|
||||
/* alignment: 4 */
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_long_long the_s_s_long_long = { 3, { 1, 2 }, 4 };
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.7
|
||||
*/
|
||||
|
||||
/* Another test for Darwin's PPC32 ABI. */
|
||||
|
||||
struct s_s_double3 {
|
||||
struct s_double2 a_s_double2; /* 16 bytes, alignment 8*/
|
||||
short another_short; /* 2 bytes */
|
||||
/* 6 bytes padding */
|
||||
}; /* total size: 24 */
|
||||
|
||||
struct s_s_s_double3 {
|
||||
struct s_s_double3 a_s_s_double3; /* 24 bytes */
|
||||
char a_char; /* 1 byte */
|
||||
/* 7 bytes padding */
|
||||
}; /* total size: 32 */
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_s_double3 the_s_s_s_double3 = { { { 1.0, 2 }, 3 }, 4 };
|
||||
|
||||
/*
|
||||
* STRUCT.ALIGNMENT.8
|
||||
*/
|
||||
|
||||
/* Same as STRUCT.ALIGNMENT.[56] but with unsigned long long. */
|
||||
|
||||
struct s_unsigned_long_long {
|
||||
unsigned long long an_unsigned_long_long; /* 8 bytes (alignment 8) */
|
||||
short a_short; /* 2 bytes */
|
||||
/* 6 bytes padding */
|
||||
}; /* total size: 16 */
|
||||
|
||||
struct s_s_unsigned_long_long {
|
||||
char a_char; /* 1 byte */
|
||||
/* 3 bytes padding */
|
||||
struct s_unsigned_long_long a_s_unsigned_long_long; /* 16 bytes, align 4 */
|
||||
short a_short; /* 2 bytes */
|
||||
/* 2 bytes padding */
|
||||
}; /* total size: 24 bytes */
|
||||
/* alignment: 4 */
|
||||
|
||||
DLLEXPORT
|
||||
struct s_s_unsigned_long_long the_s_s_unsigned_long_long = { 3, { 1, 2 }, 4 };
|
||||
|
||||
/* STRUCT.ALIGNMENT.x */
|
||||
|
||||
/* commented this test out because this is not standard C
|
||||
and MSVC++ (or some versions of it at least) won't compile it. */
|
||||
|
||||
/*
|
||||
struct empty_struct {};
|
||||
|
||||
struct with_empty_struct {
|
||||
struct empty_struct foo;
|
||||
int an_int;
|
||||
};
|
||||
|
||||
DLLEXPORT
|
||||
struct with_empty_struct the_with_empty_struct = { {}, 42 };
|
||||
*/
|
||||
|
||||
/*
|
||||
* STRUCT-VALUES.*
|
||||
*/
|
||||
|
||||
struct pair { int a, b; };
|
||||
|
||||
DLLEXPORT
|
||||
int pair_sum(struct pair p)
|
||||
{
|
||||
return p.a + p.b;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int pair_pointer_sum(struct pair *p)
|
||||
{
|
||||
return p->a + p->b;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct pair make_pair(int a, int b)
|
||||
{
|
||||
return (struct pair) { a, b };
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct pair *alloc_pair(int a, int b)
|
||||
{
|
||||
struct pair *p = malloc(sizeof(struct pair));
|
||||
p->a = a;
|
||||
p->b = b;
|
||||
return p;
|
||||
}
|
||||
|
||||
struct pair_plus_one {
|
||||
struct pair p;
|
||||
int c;
|
||||
};
|
||||
|
||||
DLLEXPORT
|
||||
int pair_plus_one_sum(struct pair_plus_one p)
|
||||
{
|
||||
return p.p.a + p.p.b + p.c;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
int pair_plus_one_pointer_sum(struct pair_plus_one *p)
|
||||
{
|
||||
return p->p.a + p->p.b + p->c;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct pair_plus_one make_pair_plus_one(int a, int b, int c)
|
||||
{
|
||||
return (struct pair_plus_one) { { a, b }, c };
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
struct pair_plus_one *alloc_pair_plus_one(int a, int b, int c)
|
||||
{
|
||||
struct pair_plus_one *p = malloc(sizeof(struct pair_plus_one));
|
||||
p->p.a = a;
|
||||
p->p.b = b;
|
||||
p->c = c;
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFCFUN.NOARGS and DEFCFUN.NOOP
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
int noargs()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
DLLEXPORT
|
||||
void noop()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFCFUN.BFF.1
|
||||
*
|
||||
* (let ((rettype (find-type :long))
|
||||
* (arg-types (n-random-types-no-ll 127)))
|
||||
* (c-function rettype arg-types)
|
||||
* (gen-function-test rettype arg-types))
|
||||
*/
|
||||
|
||||
DLLEXPORT long sum_127_no_ll
|
||||
(long a1, unsigned long a2, short a3, unsigned short a4, float a5,
|
||||
double a6, unsigned long a7, float a8, unsigned char a9, unsigned
|
||||
short a10, short a11, unsigned long a12, double a13, long a14,
|
||||
unsigned int a15, void* a16, unsigned int a17, unsigned short a18,
|
||||
long a19, float a20, void* a21, float a22, int a23, int a24, unsigned
|
||||
short a25, long a26, long a27, double a28, unsigned char a29, unsigned
|
||||
int a30, unsigned int a31, int a32, unsigned short a33, unsigned int
|
||||
a34, void* a35, double a36, double a37, long a38, short a39, unsigned
|
||||
short a40, long a41, char a42, long a43, unsigned short a44, void*
|
||||
a45, int a46, unsigned int a47, double a48, unsigned char a49,
|
||||
unsigned char a50, float a51, int a52, unsigned short a53, double a54,
|
||||
short a55, unsigned char a56, unsigned long a57, float a58, float a59,
|
||||
float a60, void* a61, void* a62, unsigned int a63, unsigned long a64,
|
||||
char a65, short a66, unsigned short a67, unsigned long a68, void* a69,
|
||||
float a70, double a71, long a72, unsigned long a73, short a74,
|
||||
unsigned int a75, unsigned short a76, int a77, unsigned short a78,
|
||||
char a79, double a80, short a81, unsigned char a82, float a83, char
|
||||
a84, int a85, double a86, unsigned char a87, int a88, unsigned long
|
||||
a89, double a90, short a91, short a92, unsigned int a93, unsigned char
|
||||
a94, float a95, long a96, float a97, long a98, long a99, int a100, int
|
||||
a101, unsigned int a102, char a103, char a104, unsigned short a105,
|
||||
unsigned int a106, unsigned short a107, unsigned short a108, int a109,
|
||||
long a110, char a111, double a112, unsigned int a113, char a114, short
|
||||
a115, unsigned long a116, unsigned int a117, short a118, unsigned char
|
||||
a119, float a120, void* a121, double a122, int a123, long a124, char
|
||||
a125, unsigned short a126, float a127)
|
||||
{
|
||||
return (long) a1 + a2 + a3 + a4 + ((long) a5) + ((long) a6) + a7 +
|
||||
((long) a8) + a9 + a10 + a11 + a12 + ((long) a13) + a14 + a15 +
|
||||
((intptr_t) a16) + a17 + a18 + a19 + ((long) a20) +
|
||||
((intptr_t) a21) + ((long) a22) + a23 + a24 + a25 + a26 + a27 +
|
||||
((long) a28) + a29 + a30 + a31 + a32 + a33 + a34 + ((intptr_t) a35) +
|
||||
((long) a36) + ((long) a37) + a38 + a39 + a40 + a41 + a42 + a43 + a44 +
|
||||
((intptr_t) a45) + a46 + a47 + ((long) a48) + a49 + a50 +
|
||||
((long) a51) + a52 + a53 + ((long) a54) + a55 + a56 + a57 + ((long) a58) +
|
||||
((long) a59) + ((long) a60) + ((intptr_t) a61) +
|
||||
((intptr_t) a62) + a63 + a64 + a65 + a66 + a67 + a68 +
|
||||
((intptr_t) a69) + ((long) a70) + ((long) a71) + a72 + a73 + a74 +
|
||||
a75 + a76 + a77 + a78 + a79 + ((long) a80) + a81 + a82 + ((long) a83) +
|
||||
a84 + a85 + ((long) a86) + a87 + a88 + a89 + ((long) a90) + a91 + a92 +
|
||||
a93 + a94 + ((long) a95) + a96 + ((long) a97) + a98 + a99 + a100 + a101 +
|
||||
a102 + a103 + a104 + a105 + a106 + a107 + a108 + a109 + a110 + a111 +
|
||||
((long) a112) + a113 + a114 + a115 + a116 + a117 + a118 + a119 +
|
||||
((long) a120) + ((intptr_t) a121) + ((long) a122) + a123 + a124 +
|
||||
a125 + a126 + ((long) a127);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFCFUN.BFF.2
|
||||
*
|
||||
* (let ((rettype (find-type :long-long))
|
||||
* (arg-types (n-random-types 127)))
|
||||
* (c-function rettype arg-types)
|
||||
* (gen-function-test rettype arg-types))
|
||||
*/
|
||||
|
||||
DLLEXPORT long long sum_127
|
||||
(void* a1, void* a2, float a3, unsigned long a4, void* a5, long long
|
||||
a6, double a7, double a8, unsigned short a9, int a10, long long a11,
|
||||
long a12, short a13, unsigned int a14, long a15, unsigned char a16,
|
||||
int a17, double a18, short a19, short a20, long long a21, unsigned
|
||||
int a22, unsigned short a23, short a24, void* a25, short a26,
|
||||
unsigned short a27, unsigned short a28, int a29, long long a30,
|
||||
void* a31, int a32, unsigned long a33, unsigned long a34, void* a35,
|
||||
unsigned long long a36, float a37, int a38, short a39, void* a40,
|
||||
unsigned long long a41, long long a42, unsigned long a43, unsigned
|
||||
long a44, unsigned long long a45, unsigned long a46, char a47,
|
||||
double a48, long a49, unsigned int a50, int a51, short a52, void*
|
||||
a53, long a54, unsigned long long a55, int a56, unsigned short a57,
|
||||
unsigned long long a58, float a59, void* a60, float a61, unsigned
|
||||
short a62, unsigned long a63, float a64, unsigned int a65, unsigned
|
||||
long long a66, void* a67, double a68, unsigned long long a69, double
|
||||
a70, double a71, long long a72, void* a73, unsigned short a74, long
|
||||
a75, void* a76, short a77, double a78, long a79, unsigned char a80,
|
||||
void* a81, unsigned char a82, long a83, double a84, void* a85, int
|
||||
a86, double a87, unsigned char a88, double a89, short a90, long a91,
|
||||
int a92, long a93, double a94, unsigned short a95, unsigned int a96,
|
||||
int a97, char a98, long long a99, double a100, float a101, unsigned
|
||||
long a102, short a103, void* a104, float a105, long long a106, int
|
||||
a107, long long a108, long long a109, double a110, unsigned long
|
||||
long a111, double a112, unsigned long a113, char a114, char a115,
|
||||
unsigned long a116, short a117, unsigned char a118, unsigned char
|
||||
a119, int a120, int a121, float a122, unsigned char a123, unsigned
|
||||
char a124, double a125, unsigned long long a126, char a127)
|
||||
{
|
||||
return (long long) ((intptr_t) a1) + ((intptr_t) a2) + ((long) a3) +
|
||||
a4 + ((intptr_t) a5) + a6 + ((long) a7) + ((long) a8) + a9 + a10 +
|
||||
a11 + a12 + a13 + a14 + a15 + a16 + a17 + ((long) a18) + a19 + a20 +
|
||||
a21 + a22 + a23 + a24 + ((intptr_t) a25) + a26 + a27 + a28 + a29 +
|
||||
a30 + ((intptr_t) a31) + a32 + a33 + a34 + ((intptr_t) a35) +
|
||||
a36 + ((long) a37) + a38 + a39 + ((intptr_t) a40) + a41 + a42 + a43 +
|
||||
a44 + a45 + a46 + a47 + ((long) a48) + a49 + a50 + a51 + a52 +
|
||||
((intptr_t) a53) + a54 + a55 + a56 + a57 + a58 + ((long) a59) +
|
||||
((intptr_t) a60) + ((long) a61) + a62 + a63 + ((long) a64) + a65 + a66
|
||||
+ ((intptr_t) a67) + ((long) a68) + a69 + ((long) a70) + ((long) a71) +
|
||||
a72 + ((intptr_t) a73) + a74 + a75 + ((intptr_t) a76) + a77 +
|
||||
((long) a78) + a79 + a80 + ((intptr_t) a81) + a82 + a83 + ((long) a84)
|
||||
+ ((intptr_t) a85) + a86 + ((long) a87) + a88 + ((long) a89) + a90 +
|
||||
a91 + a92 + a93 + ((long) a94) + a95 + a96 + a97 + a98 + a99 +
|
||||
((long) a100) + ((long) a101) + a102 + a103 + ((intptr_t) a104) +
|
||||
((long) a105) + a106 + a107 + a108 + a109 + ((long) a110) + a111 +
|
||||
((long) a112) + a113 + a114 + a115 + a116 + a117 + a118 + a119 + a120 +
|
||||
a121 + ((long) a122) + a123 + a124 + ((long) a125) + a126 + a127;
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACKS.BFF.1 (cb-test :no-long-long t)
|
||||
*/
|
||||
|
||||
DLLEXPORT long call_sum_127_no_ll
|
||||
(long (*func)
|
||||
(unsigned long, void*, long, double, unsigned long, float, float,
|
||||
int, unsigned int, double, double, double, void*, unsigned short,
|
||||
unsigned short, void*, long, long, int, short, unsigned short,
|
||||
unsigned short, char, long, void*, void*, char, unsigned char,
|
||||
unsigned long, short, int, int, unsigned char, short, long, long,
|
||||
void*, unsigned short, char, double, unsigned short, void*, short,
|
||||
unsigned long, unsigned short, float, unsigned char, short, float,
|
||||
short, char, unsigned long, unsigned long, char, float, long, void*,
|
||||
short, float, unsigned int, float, unsigned int, double, unsigned int,
|
||||
unsigned char, int, long, char, short, double, int, void*, char,
|
||||
unsigned short, void*, unsigned short, void*, unsigned long, double,
|
||||
void*, long, float, unsigned short, unsigned short, void*, float, int,
|
||||
unsigned int, double, float, long, void*, unsigned short, float,
|
||||
unsigned char, unsigned char, float, unsigned int, float, unsigned
|
||||
short, double, unsigned short, unsigned long, unsigned int, unsigned
|
||||
long, void*, unsigned char, char, char, unsigned short, unsigned long,
|
||||
float, short, void*, long, unsigned short, short, double, short, int,
|
||||
char, unsigned long, long, int, void*, double, unsigned char))
|
||||
{
|
||||
return
|
||||
func(948223085, (void *) 803308438, -465723152, 20385,
|
||||
219679466, -10035, 13915, -1193455756, 1265303699, 27935, -18478,
|
||||
-10508, (void *) 215389089, 55561, 55472, (void *) 146070433,
|
||||
-1040819989, -17851453, -1622662247, -19473, 20837, 30216, 79,
|
||||
986800400, (void *) 390281604, (void *) 1178532858, 19, 117,
|
||||
78337699, -5718, -991300738, 872160910, 184, 926, -1487245383,
|
||||
1633973783, (void *) 33738609, 53985, -116, 31645, 27196, (void *)
|
||||
145569903, -6960, 17252220, 47404, -10491, 88, -30438, -21212,
|
||||
-1982, -16, 1175270, 7949380, -121, 8559, -432968526, (void *)
|
||||
293455312, 11894, -8394, 142421516, -25758, 3422998, 4004,
|
||||
15758212, 198, -1071899743, -1284904617, -11, -17219, -30039,
|
||||
311589092, (void *) 541468577, 123, 63517, (void *) 1252504506,
|
||||
39368, (void *) 10057868, 134781408, -7143, (void *) 72825877,
|
||||
-1190798667, -30862, 63757, 14965, (void *) 802391252, 22008,
|
||||
-517289619, 806091099, 1125, 451, -498145176, (void *) 55960931,
|
||||
15379, 4629, 184, 254, 22532, 465856451, -1669, 49416, -16546,
|
||||
2983, 4337541, 65292495, 39253529, (void *) 669025, 211, 85, -19,
|
||||
24298, 65358, 16776, -29957, (void *) 124311, -163231228, 2610,
|
||||
-7806, 26434, -21913, -753615541, 120, 358697932, -1198889034,
|
||||
-2131350926, (void *) 3749492036, -13413, 17);
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACKS.BFF.2 (cb-test)
|
||||
*/
|
||||
|
||||
DLLEXPORT long long call_sum_127
|
||||
(long long (*func)
|
||||
(short, char, void*, float, long, double, unsigned long long,
|
||||
unsigned short, unsigned char, char, char, unsigned short, unsigned
|
||||
long long, unsigned short, long long, unsigned short, unsigned long
|
||||
long, unsigned char, unsigned char, unsigned long long, long long,
|
||||
char, float, unsigned int, float, float, unsigned int, float, char,
|
||||
unsigned char, long, long long, unsigned char, double, long,
|
||||
double, unsigned int, unsigned short, long long, unsigned int, int,
|
||||
unsigned long long, long, short, unsigned int, unsigned int,
|
||||
unsigned long long, unsigned int, long, void*, unsigned char, char,
|
||||
long long, unsigned short, unsigned int, float, unsigned char,
|
||||
unsigned long, long long, float, long, float, int, float, unsigned
|
||||
short, unsigned long long, short, unsigned long, long, char,
|
||||
unsigned short, long long, short, double, void*, unsigned int,
|
||||
char, unsigned int, void*, void*, unsigned char, void*, unsigned
|
||||
short, unsigned char, long, void*, char, long, unsigned short,
|
||||
unsigned char, double, unsigned long long, unsigned short, unsigned
|
||||
short, unsigned int, long, char, long, char, short, unsigned short,
|
||||
unsigned long, unsigned long, short, long long, long long, long
|
||||
long, double, unsigned short, unsigned char, short, unsigned char,
|
||||
long, long long, unsigned long long, unsigned int, unsigned long,
|
||||
unsigned char, long long, unsigned char, unsigned long long,
|
||||
double, unsigned char, long long, unsigned char, char, long long))
|
||||
{
|
||||
return
|
||||
func(-8573, 14, (void *) 832601021, -32334, -1532040888,
|
||||
-18478, 2793023182591311826, 2740, 230, 103, 97, 13121,
|
||||
5112369026351511084, 7763, -8134147951003417418, 34348,
|
||||
5776613699556468853, 19, 122, 1431603726926527625,
|
||||
439503521880490337, -112, -21557, 1578969190, -22008, -4953,
|
||||
2127745975, -7262, -6, 180, 226352974, -3928775366167459219, 134,
|
||||
-17730, -1175042526, 23868, 3494181009, 57364,
|
||||
3134876875147518682, 104531655, -1286882727, 803577887579693487,
|
||||
1349268803, 24912, 3313099419, 3907347884, 1738833249233805034,
|
||||
2794230885, 1008818752, (void *) 1820044575, 189, 61,
|
||||
-931654560961745071, 57531, 3096859985, 10405, 220, 3631311224,
|
||||
-8531370353478907668, 31258, 678896693, -32150, -1869057813,
|
||||
-19877, 62841, 4161660185772906873, -23869, 4016251006, 610353435,
|
||||
105, 47315, -1051054492535331660, 6846, -15163, (void *)
|
||||
736672359, 2123928476, -122, 3859258652, (void *) 3923394833,
|
||||
(void *) 1265031970, 161, (void *) 1993867800, 55056, 122,
|
||||
1562112760, (void *) 866615125, -79, -1261399547, 31737, 254,
|
||||
-31279, 5462649659172897980, 5202, 7644, 174224940, -337854382,
|
||||
-45, -583502442, -37, -13266, 24520, 2198606699, 2890453969,
|
||||
-8282, -2295716637858246075, -1905178488651598878,
|
||||
-6384652209316714643, 14841, 35443, 132, 15524, 187, 2138878229,
|
||||
-5153032566879951000, 9056545530140684207, 4124632010, 276167701,
|
||||
56, -2307310370663738730, 66, 9113015627153789746, -9618, 167,
|
||||
755753399701306200, 119, -28, -990561962725435433);
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACKS.DOUBLE26
|
||||
*/
|
||||
|
||||
DLLEXPORT double call_double26
|
||||
(double (*f)(double, double, double, double, double, double, double, double,
|
||||
double, double, double, double, double, double, double, double,
|
||||
double, double, double, double, double, double, double, double,
|
||||
double, double))
|
||||
{
|
||||
return f(3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14,
|
||||
3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14, 3.14,
|
||||
3.14, 3.14, 3.14, 3.14);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFCFUN.DOUBLE26 and FUNCALL.DOUBLE26
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
double sum_double26(double a1, double a2, double a3, double a4, double a5,
|
||||
double a6, double a7, double a8, double a9, double a10,
|
||||
double a11, double a12, double a13, double a14, double a15,
|
||||
double a16, double a17, double a18, double a19, double a20,
|
||||
double a21, double a22, double a23, double a24, double a25,
|
||||
double a26)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 +
|
||||
a14 + a15 + a16 + a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 + a25 +
|
||||
a26;
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFCFUN.VARARGS.NOSTDLIB and FUNCALL.VARARGS.NOSTDLIB
|
||||
*/
|
||||
DLLEXPORT
|
||||
double sum_double_arbitrary(int n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
double sum = 0;
|
||||
va_start(ap, n);
|
||||
for(int j=0; j<n; j++)
|
||||
sum += va_arg(ap, double);
|
||||
va_end(ap);
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACKS.FLOAT26
|
||||
*/
|
||||
|
||||
DLLEXPORT float call_float26
|
||||
(float (*f)(float, float, float, float, float, float, float, float,
|
||||
float, float, float, float, float, float, float, float,
|
||||
float, float, float, float, float, float, float, float,
|
||||
float, float))
|
||||
{
|
||||
return f(5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0,
|
||||
5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0,
|
||||
5.0, 5.0, 5.0, 5.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFCFUN.FLOAT26 and FUNCALL.FLOAT26
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
float sum_float26(float a1, float a2, float a3, float a4, float a5,
|
||||
float a6, float a7, float a8, float a9, float a10,
|
||||
float a11, float a12, float a13, float a14, float a15,
|
||||
float a16, float a17, float a18, float a19, float a20,
|
||||
float a21, float a22, float a23, float a24, float a25,
|
||||
float a26)
|
||||
{
|
||||
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 +
|
||||
a14 + a15 + a16 + a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 + a25 +
|
||||
a26;
|
||||
}
|
||||
|
||||
/*
|
||||
* Symbol case.
|
||||
*/
|
||||
|
||||
DLLEXPORT int UPPERCASEINT1 = 12345;
|
||||
DLLEXPORT int UPPER_CASE_INT1 = 23456;
|
||||
DLLEXPORT int MiXeDCaSeInT1 = 34567;
|
||||
DLLEXPORT int MiXeD_CaSe_InT1 = 45678;
|
||||
|
||||
DLLEXPORT int UPPERCASEINT2 = 12345;
|
||||
DLLEXPORT int UPPER_CASE_INT2 = 23456;
|
||||
DLLEXPORT int MiXeDCaSeInT2 = 34567;
|
||||
DLLEXPORT int MiXeD_CaSe_InT2 = 45678;
|
||||
|
||||
DLLEXPORT int UPPERCASEINT3 = 12345;
|
||||
DLLEXPORT int UPPER_CASE_INT3 = 23456;
|
||||
DLLEXPORT int MiXeDCaSeInT3 = 34567;
|
||||
DLLEXPORT int MiXeD_CaSe_InT3 = 45678;
|
||||
|
||||
/*
|
||||
* FOREIGN-SYMBOL-POINTER.1
|
||||
*/
|
||||
|
||||
DLLEXPORT int compare_against_abs(intptr_t p)
|
||||
{
|
||||
return p == (intptr_t) abs;
|
||||
}
|
||||
|
||||
/*
|
||||
* FOREIGN-SYMBOL-POINTER.2
|
||||
*/
|
||||
|
||||
DLLEXPORT void xpto_fun() {}
|
||||
|
||||
DLLEXPORT
|
||||
int compare_against_xpto_fun(intptr_t p)
|
||||
{
|
||||
return p == (intptr_t) xpto_fun;
|
||||
}
|
||||
|
||||
/*
|
||||
* [DEFCFUN|FUNCALL].NAMESPACE.1
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
int ns_function()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* FOREIGN-GLOBALS.NAMESPACE.*
|
||||
*/
|
||||
|
||||
DLLEXPORT int ns_var = 1;
|
||||
|
||||
/*
|
||||
* DEFCFUN.STDCALL.1
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
int STDCALL stdcall_fun(int a, int b, int c)
|
||||
{
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACKS.STDCALL.1
|
||||
*/
|
||||
|
||||
DLLEXPORT
|
||||
int call_stdcall_fun(int (STDCALL *f)(int, int, int))
|
||||
{
|
||||
int a = 42;
|
||||
f(1, 2, 3);
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Unlike the one above, this commented test below actually
|
||||
* works. But, alas, it doesn't compile with -std=c99. */
|
||||
|
||||
/*
|
||||
DLLEXPORT
|
||||
int call_stdcall_fun(int __attribute__((stdcall)) (*f)(int, int, int))
|
||||
{
|
||||
asm("pushl $42");
|
||||
register int ebx asm("%ebx");
|
||||
f(1, 2, 3);
|
||||
asm("popl %ebx");
|
||||
return ebx;
|
||||
}
|
||||
*/
|
||||
|
||||
/* vim: ts=4 et
|
||||
*/
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*-
|
||||
*
|
||||
* libtest2.c --- auxiliary C lib for testing purposes
|
||||
*
|
||||
* Copyright (C) 2007, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* [DEFCFUN|FOREIGN].NAMESPACE.1
|
||||
*/
|
||||
|
||||
DLLEXPORT int ns_function()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FOREIGN-GLOBALS.NAMESPACE.*
|
||||
*/
|
||||
|
||||
DLLEXPORT int ns_var = 0;
|
||||
|
||||
/* vim: ts=4 et
|
||||
*/
|
||||
|
|
@ -0,0 +1,657 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; memory.lisp --- Tests for memory referencing.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, James Bielman <jamesjb@jamesjb.com>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(deftest deref.char
|
||||
(with-foreign-object (p :char)
|
||||
(setf (mem-ref p :char) -127)
|
||||
(mem-ref p :char))
|
||||
-127)
|
||||
|
||||
(deftest deref.unsigned-char
|
||||
(with-foreign-object (p :unsigned-char)
|
||||
(setf (mem-ref p :unsigned-char) 255)
|
||||
(mem-ref p :unsigned-char))
|
||||
255)
|
||||
|
||||
(deftest deref.short
|
||||
(with-foreign-object (p :short)
|
||||
(setf (mem-ref p :short) -32767)
|
||||
(mem-ref p :short))
|
||||
-32767)
|
||||
|
||||
(deftest deref.unsigned-short
|
||||
(with-foreign-object (p :unsigned-short)
|
||||
(setf (mem-ref p :unsigned-short) 65535)
|
||||
(mem-ref p :unsigned-short))
|
||||
65535)
|
||||
|
||||
(deftest deref.int
|
||||
(with-foreign-object (p :int)
|
||||
(setf (mem-ref p :int) -131072)
|
||||
(mem-ref p :int))
|
||||
-131072)
|
||||
|
||||
(deftest deref.unsigned-int
|
||||
(with-foreign-object (p :unsigned-int)
|
||||
(setf (mem-ref p :unsigned-int) 262144)
|
||||
(mem-ref p :unsigned-int))
|
||||
262144)
|
||||
|
||||
(deftest deref.long
|
||||
(with-foreign-object (p :long)
|
||||
(setf (mem-ref p :long) -536870911)
|
||||
(mem-ref p :long))
|
||||
-536870911)
|
||||
|
||||
(deftest deref.unsigned-long
|
||||
(with-foreign-object (p :unsigned-long)
|
||||
(setf (mem-ref p :unsigned-long) 536870912)
|
||||
(mem-ref p :unsigned-long))
|
||||
536870912)
|
||||
|
||||
#+(and darwin openmcl)
|
||||
(pushnew 'deref.long-long rt::*expected-failures*)
|
||||
|
||||
(deftest deref.long-long
|
||||
(with-foreign-object (p :long-long)
|
||||
(setf (mem-ref p :long-long) -9223372036854775807)
|
||||
(mem-ref p :long-long))
|
||||
-9223372036854775807)
|
||||
|
||||
(deftest deref.unsigned-long-long
|
||||
(with-foreign-object (p :unsigned-long-long)
|
||||
(setf (mem-ref p :unsigned-long-long) 18446744073709551615)
|
||||
(mem-ref p :unsigned-long-long))
|
||||
18446744073709551615)
|
||||
|
||||
(deftest deref.float.1
|
||||
(with-foreign-object (p :float)
|
||||
(setf (mem-ref p :float) 0.0)
|
||||
(mem-ref p :float))
|
||||
0.0)
|
||||
|
||||
(deftest deref.float.2
|
||||
(with-foreign-object (p :float)
|
||||
(setf (mem-ref p :float) *float-max*)
|
||||
(mem-ref p :float))
|
||||
#.*float-max*)
|
||||
|
||||
(deftest deref.float.3
|
||||
(with-foreign-object (p :float)
|
||||
(setf (mem-ref p :float) *float-min*)
|
||||
(mem-ref p :float))
|
||||
#.*float-min*)
|
||||
|
||||
(deftest deref.double.1
|
||||
(with-foreign-object (p :double)
|
||||
(setf (mem-ref p :double) 0.0d0)
|
||||
(mem-ref p :double))
|
||||
0.0d0)
|
||||
|
||||
(deftest deref.double.2
|
||||
(with-foreign-object (p :double)
|
||||
(setf (mem-ref p :double) *double-max*)
|
||||
(mem-ref p :double))
|
||||
#.*double-max*)
|
||||
|
||||
(deftest deref.double.3
|
||||
(with-foreign-object (p :double)
|
||||
(setf (mem-ref p :double) *double-min*)
|
||||
(mem-ref p :double))
|
||||
#.*double-min*)
|
||||
|
||||
;;; TODO: use something like *DOUBLE-MIN/MAX* above once we actually
|
||||
;;; have an available lisp that supports long double.
|
||||
;#-cffi-sys::no-long-float
|
||||
#+(and scl long-double)
|
||||
(progn
|
||||
(deftest deref.long-double.1
|
||||
(with-foreign-object (p :long-double)
|
||||
(setf (mem-ref p :long-double) 0.0l0)
|
||||
(mem-ref p :long-double))
|
||||
0.0l0)
|
||||
|
||||
(deftest deref.long-double.2
|
||||
(with-foreign-object (p :long-double)
|
||||
(setf (mem-ref p :long-double) most-positive-long-float)
|
||||
(mem-ref p :long-double))
|
||||
#.most-positive-long-float)
|
||||
|
||||
(deftest deref.long-double.3
|
||||
(with-foreign-object (p :long-double)
|
||||
(setf (mem-ref p :long-double) least-positive-long-float)
|
||||
(mem-ref p :long-double))
|
||||
#.least-positive-long-float))
|
||||
|
||||
;;; make sure the lisp doesn't convert NULL to NIL
|
||||
(deftest deref.pointer.null
|
||||
(with-foreign-object (p :pointer)
|
||||
(setf (mem-ref p :pointer) (null-pointer))
|
||||
(null-pointer-p (mem-ref p :pointer)))
|
||||
t)
|
||||
|
||||
;;; regression test. lisp-string-to-foreign should handle empty strings
|
||||
(deftest lisp-string-to-foreign.empty
|
||||
(with-foreign-pointer (str 2)
|
||||
(setf (mem-ref str :unsigned-char) 42)
|
||||
(lisp-string-to-foreign "" str 1)
|
||||
(mem-ref str :unsigned-char))
|
||||
0)
|
||||
|
||||
;;; regression test. with-foreign-pointer shouldn't evaluate
|
||||
;;; the size argument twice.
|
||||
(deftest with-foreign-pointer.evalx2
|
||||
(let ((count 0))
|
||||
(with-foreign-pointer (x (incf count) size-var)
|
||||
(values count size-var)))
|
||||
1 1)
|
||||
|
||||
(defconstant +two+ 2)
|
||||
|
||||
;;; regression test. cffi-allegro's with-foreign-pointer wasn't
|
||||
;;; handling constants properly.
|
||||
(deftest with-foreign-pointer.constant-size
|
||||
(with-foreign-pointer (p +two+ size)
|
||||
size)
|
||||
2)
|
||||
|
||||
(deftest mem-ref.left-to-right
|
||||
(let ((i 0))
|
||||
(with-foreign-object (p :char 3)
|
||||
(setf (mem-ref p :char 0) 66 (mem-ref p :char 1) 92)
|
||||
(setf (mem-ref p :char (incf i)) (incf i))
|
||||
(values (mem-ref p :char 0) (mem-ref p :char 1) i)))
|
||||
66 2 2)
|
||||
|
||||
;;; This needs to be in a real function for at least Allegro CL or the
|
||||
;;; compiler macro on %MEM-REF is not expanded and the test doesn't
|
||||
;;; actually test anything!
|
||||
(defun %mem-ref-left-to-right ()
|
||||
(let ((result nil))
|
||||
(with-foreign-object (p :char)
|
||||
(%mem-set 42 p :char)
|
||||
(%mem-ref (progn (push 1 result) p) :char (progn (push 2 result) 0))
|
||||
(nreverse result))))
|
||||
|
||||
;;; Test left-to-right evaluation of the arguments to %MEM-REF when
|
||||
;;; optimized by the compiler macro.
|
||||
(deftest %mem-ref.left-to-right
|
||||
(%mem-ref-left-to-right)
|
||||
(1 2))
|
||||
|
||||
;;; This needs to be in a top-level function for at least Allegro CL
|
||||
;;; or the compiler macro on %MEM-SET is not expanded and the test
|
||||
;;; doesn't actually test anything!
|
||||
(defun %mem-set-left-to-right ()
|
||||
(let ((result nil))
|
||||
(with-foreign-object (p :char)
|
||||
(%mem-set (progn (push 1 result) 0)
|
||||
(progn (push 2 result) p)
|
||||
:char
|
||||
(progn (push 3 result) 0))
|
||||
(nreverse result))))
|
||||
|
||||
;;; Test left-to-right evaluation of the arguments to %MEM-SET when
|
||||
;;; optimized by the compiler macro.
|
||||
(deftest %mem-set.left-to-right
|
||||
(%mem-set-left-to-right)
|
||||
(1 2 3))
|
||||
|
||||
;; regression test. mem-aref's setf expansion evaluated its type argument twice.
|
||||
(deftest mem-aref.eval-type-x2
|
||||
(let ((count 0))
|
||||
(with-foreign-pointer (p 1)
|
||||
(setf (mem-aref p (progn (incf count) :char) 0) 127))
|
||||
count)
|
||||
1)
|
||||
|
||||
(deftest mem-aref.left-to-right
|
||||
(let ((count -1))
|
||||
(with-foreign-pointer (p 2)
|
||||
(values
|
||||
(setf (mem-aref p (progn (incf count) :char) (incf count)) (incf count))
|
||||
(setq count -1)
|
||||
(mem-aref (progn (incf count) p) :char (incf count))
|
||||
count)))
|
||||
2 -1 2 1)
|
||||
|
||||
;; regression tests. nested mem-ref's and mem-aref's had bogus getters
|
||||
(deftest mem-ref.nested
|
||||
(with-foreign-object (p :pointer)
|
||||
(with-foreign-object (i :int)
|
||||
(setf (mem-ref p :pointer) i)
|
||||
(setf (mem-ref i :int) 42)
|
||||
(setf (mem-ref (mem-ref p :pointer) :int) 1984)
|
||||
(mem-ref i :int)))
|
||||
1984)
|
||||
|
||||
(deftest mem-aref.nested
|
||||
(with-foreign-object (p :pointer)
|
||||
(with-foreign-object (i :int 2)
|
||||
(setf (mem-aref p :pointer 0) i)
|
||||
(setf (mem-aref i :int 1) 42)
|
||||
(setf (mem-aref (mem-ref p :pointer 0) :int 1) 1984)
|
||||
(mem-aref i :int 1)))
|
||||
1984)
|
||||
|
||||
(cffi:defcstruct mem-aref.bare-struct
|
||||
(a :uint8))
|
||||
|
||||
;;; regression test: although mem-aref was dealing with bare struct
|
||||
;;; types as though they were pointers, it wasn't calculating the
|
||||
;;; proper offsets. The offsets for bare structs types should be
|
||||
;;; calculated as aggregate types.
|
||||
(deftest mem-aref.bare-struct
|
||||
(with-foreign-object (a 'mem-aref.bare-struct 2)
|
||||
(eql (- (pointer-address (cffi:mem-aref a 'mem-aref.bare-struct 1))
|
||||
(pointer-address (cffi:mem-aref a 'mem-aref.bare-struct 0)))
|
||||
(foreign-type-size '(:struct mem-aref.bare-struct))))
|
||||
t)
|
||||
|
||||
;;; regression tests. dereferencing an aggregate type. dereferencing a
|
||||
;;; struct should return a pointer to the struct itself, not return the
|
||||
;;; first 4 bytes (or whatever the size of :pointer is) as a pointer.
|
||||
;;;
|
||||
;;; This important for accessing an array of structs, which is
|
||||
;;; what the deref.array-of-aggregates test does.
|
||||
(defcstruct some-struct (x :int))
|
||||
|
||||
(deftest deref.aggregate
|
||||
(with-foreign-object (s 'some-struct)
|
||||
(pointer-eq s (mem-ref s 'some-struct)))
|
||||
t)
|
||||
|
||||
(deftest deref.array-of-aggregates
|
||||
(with-foreign-object (arr 'some-struct 3)
|
||||
(loop for i below 3
|
||||
do (setf (foreign-slot-value (mem-aref arr 'some-struct i)
|
||||
'some-struct 'x)
|
||||
112))
|
||||
(loop for i below 3
|
||||
collect (foreign-slot-value (mem-aref arr 'some-struct i)
|
||||
'some-struct 'x)))
|
||||
(112 112 112))
|
||||
|
||||
;;; pointer operations
|
||||
(deftest pointer.1
|
||||
(pointer-address (make-pointer 42))
|
||||
42)
|
||||
|
||||
;;; I suppose this test is not very good. --luis
|
||||
(deftest pointer.2
|
||||
(pointer-address (null-pointer))
|
||||
0)
|
||||
|
||||
(deftest pointer.null
|
||||
(nth-value 0 (ignore-errors (null-pointer-p nil)))
|
||||
nil)
|
||||
|
||||
(deftest foreign-pointer-type.nil
|
||||
(typep nil 'foreign-pointer)
|
||||
nil)
|
||||
|
||||
;;; Ensure that a pointer to the highest possible address can be
|
||||
;;; created using MAKE-POINTER. Regression test for CLISP/X86-64.
|
||||
(deftest make-pointer.high
|
||||
(let* ((pointer-length (foreign-type-size :pointer))
|
||||
(high-address (1- (expt 2 (* pointer-length 8))))
|
||||
(pointer (make-pointer high-address)))
|
||||
(- high-address (pointer-address pointer)))
|
||||
0)
|
||||
|
||||
;;; Ensure that incrementing a pointer by zero bytes returns an
|
||||
;;; equivalent pointer.
|
||||
(deftest inc-pointer.zero
|
||||
(with-foreign-object (x :int)
|
||||
(pointer-eq x (inc-pointer x 0)))
|
||||
t)
|
||||
|
||||
;;; Test the INITIAL-ELEMENT keyword argument to FOREIGN-ALLOC.
|
||||
(deftest foreign-alloc.1
|
||||
(let ((ptr (foreign-alloc :int :initial-element 42)))
|
||||
(unwind-protect
|
||||
(mem-ref ptr :int)
|
||||
(foreign-free ptr)))
|
||||
42)
|
||||
|
||||
;;; Test the INITIAL-ELEMENT and COUNT arguments to FOREIGN-ALLOC.
|
||||
(deftest foreign-alloc.2
|
||||
(let ((ptr (foreign-alloc :int :count 4 :initial-element 100)))
|
||||
(unwind-protect
|
||||
(loop for i from 0 below 4
|
||||
collect (mem-aref ptr :int i))
|
||||
(foreign-free ptr)))
|
||||
(100 100 100 100))
|
||||
|
||||
;;; Test the INITIAL-CONTENTS and COUNT arguments to FOREIGN-ALLOC,
|
||||
;;; passing a list of initial values.
|
||||
(deftest foreign-alloc.3
|
||||
(let ((ptr (foreign-alloc :int :count 4 :initial-contents '(4 3 2 1))))
|
||||
(unwind-protect
|
||||
(loop for i from 0 below 4
|
||||
collect (mem-aref ptr :int i))
|
||||
(foreign-free ptr)))
|
||||
(4 3 2 1))
|
||||
|
||||
;;; Test INITIAL-CONTENTS and COUNT with FOREIGN-ALLOC passing a
|
||||
;;; vector of initial values.
|
||||
(deftest foreign-alloc.4
|
||||
(let ((ptr (foreign-alloc :int :count 4 :initial-contents #(10 20 30 40))))
|
||||
(unwind-protect
|
||||
(loop for i from 0 below 4
|
||||
collect (mem-aref ptr :int i))
|
||||
(foreign-free ptr)))
|
||||
(10 20 30 40))
|
||||
|
||||
;;; Ensure calling FOREIGN-ALLOC with both INITIAL-ELEMENT and
|
||||
;;; INITIAL-CONTENTS signals an error.
|
||||
(deftest foreign-alloc.5
|
||||
(values
|
||||
(ignore-errors
|
||||
(let ((ptr (foreign-alloc :int :initial-element 1
|
||||
:initial-contents '(1))))
|
||||
(foreign-free ptr))
|
||||
t))
|
||||
nil)
|
||||
|
||||
;;; Regression test: FOREIGN-ALLOC shouldn't actually perform translation
|
||||
;;; on initial-element/initial-contents since MEM-AREF will do that already.
|
||||
(define-foreign-type not-an-int ()
|
||||
()
|
||||
(:actual-type :int)
|
||||
(:simple-parser not-an-int))
|
||||
|
||||
(defmethod translate-to-foreign (value (type not-an-int))
|
||||
(assert (not (integerp value)))
|
||||
0)
|
||||
|
||||
(deftest foreign-alloc.6
|
||||
(let ((ptr (foreign-alloc 'not-an-int :initial-element 'foooo)))
|
||||
(foreign-free ptr)
|
||||
t)
|
||||
t)
|
||||
|
||||
;;; Ensure calling FOREIGN-ALLOC with NULL-TERMINATED-P and a non-pointer
|
||||
;;; type signals an error.
|
||||
(deftest foreign-alloc.7
|
||||
(values
|
||||
(ignore-errors
|
||||
(let ((ptr (foreign-alloc :int :null-terminated-p t)))
|
||||
(foreign-free ptr))
|
||||
t))
|
||||
nil)
|
||||
|
||||
;;; The opposite of the above test.
|
||||
(defctype pointer-alias :pointer)
|
||||
|
||||
(deftest foreign-alloc.8
|
||||
(progn
|
||||
(foreign-free (foreign-alloc 'pointer-alias :count 0 :null-terminated-p t))
|
||||
t)
|
||||
t)
|
||||
|
||||
;;; Ensure calling FOREIGN-ALLOC with NULL-TERMINATED-P actually places
|
||||
;;; a null pointer at the end. Not a very reliable test apparently.
|
||||
(deftest foreign-alloc.9
|
||||
(let ((ptr (foreign-alloc :pointer :count 0 :null-terminated-p t)))
|
||||
(unwind-protect
|
||||
(null-pointer-p (mem-ref ptr :pointer))
|
||||
(foreign-free ptr)))
|
||||
t)
|
||||
|
||||
;;; RT: FOREIGN-ALLOC with :COUNT 0 on CLISP signalled an error.
|
||||
(deftest foreign-alloc.10
|
||||
(null (foreign-free (foreign-alloc :char :count 0)))
|
||||
t)
|
||||
|
||||
;;; Tests for mem-ref with a non-constant type. This is a way to test
|
||||
;;; the functional interface (without compiler macros).
|
||||
|
||||
(deftest deref.nonconst.char
|
||||
(let ((type :char))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) -127)
|
||||
(mem-ref p type)))
|
||||
-127)
|
||||
|
||||
(deftest deref.nonconst.unsigned-char
|
||||
(let ((type :unsigned-char))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) 255)
|
||||
(mem-ref p type)))
|
||||
255)
|
||||
|
||||
(deftest deref.nonconst.short
|
||||
(let ((type :short))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) -32767)
|
||||
(mem-ref p type)))
|
||||
-32767)
|
||||
|
||||
(deftest deref.nonconst.unsigned-short
|
||||
(let ((type :unsigned-short))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) 65535)
|
||||
(mem-ref p type)))
|
||||
65535)
|
||||
|
||||
(deftest deref.nonconst.int
|
||||
(let ((type :int))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) -131072)
|
||||
(mem-ref p type)))
|
||||
-131072)
|
||||
|
||||
(deftest deref.nonconst.unsigned-int
|
||||
(let ((type :unsigned-int))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) 262144)
|
||||
(mem-ref p type)))
|
||||
262144)
|
||||
|
||||
(deftest deref.nonconst.long
|
||||
(let ((type :long))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) -536870911)
|
||||
(mem-ref p type)))
|
||||
-536870911)
|
||||
|
||||
(deftest deref.nonconst.unsigned-long
|
||||
(let ((type :unsigned-long))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) 536870912)
|
||||
(mem-ref p type)))
|
||||
536870912)
|
||||
|
||||
#+(and darwin openmcl)
|
||||
(pushnew 'deref.nonconst.long-long rt::*expected-failures*)
|
||||
|
||||
(deftest deref.nonconst.long-long
|
||||
(let ((type :long-long))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) -9223372036854775807)
|
||||
(mem-ref p type)))
|
||||
-9223372036854775807)
|
||||
|
||||
(deftest deref.nonconst.unsigned-long-long
|
||||
(let ((type :unsigned-long-long))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) 18446744073709551615)
|
||||
(mem-ref p type)))
|
||||
18446744073709551615)
|
||||
|
||||
(deftest deref.nonconst.float.1
|
||||
(let ((type :float))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) 0.0)
|
||||
(mem-ref p type)))
|
||||
0.0)
|
||||
|
||||
(deftest deref.nonconst.float.2
|
||||
(let ((type :float))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) *float-max*)
|
||||
(mem-ref p type)))
|
||||
#.*float-max*)
|
||||
|
||||
(deftest deref.nonconst.float.3
|
||||
(let ((type :float))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) *float-min*)
|
||||
(mem-ref p type)))
|
||||
#.*float-min*)
|
||||
|
||||
(deftest deref.nonconst.double.1
|
||||
(let ((type :double))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) 0.0d0)
|
||||
(mem-ref p type)))
|
||||
0.0d0)
|
||||
|
||||
(deftest deref.nonconst.double.2
|
||||
(let ((type :double))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) *double-max*)
|
||||
(mem-ref p type)))
|
||||
#.*double-max*)
|
||||
|
||||
(deftest deref.nonconst.double.3
|
||||
(let ((type :double))
|
||||
(with-foreign-object (p type)
|
||||
(setf (mem-ref p type) *double-min*)
|
||||
(mem-ref p type)))
|
||||
#.*double-min*)
|
||||
|
||||
;;; regression tests: lispworks's %mem-ref and %mem-set compiler
|
||||
;;; macros were misbehaving.
|
||||
|
||||
(defun mem-ref-rt-1 ()
|
||||
(with-foreign-object (a :int 2)
|
||||
(setf (mem-aref a :int 0) 123
|
||||
(mem-aref a :int 1) 456)
|
||||
(values (mem-aref a :int 0) (mem-aref a :int 1))))
|
||||
|
||||
(deftest mem-ref.rt.1
|
||||
(mem-ref-rt-1)
|
||||
123 456)
|
||||
|
||||
(defun mem-ref-rt-2 ()
|
||||
(with-foreign-object (a :double 2)
|
||||
(setf (mem-aref a :double 0) 123.0d0
|
||||
(mem-aref a :double 1) 456.0d0)
|
||||
(values (mem-aref a :double 0) (mem-aref a :double 1))))
|
||||
|
||||
(deftest mem-ref.rt.2
|
||||
(mem-ref-rt-2)
|
||||
123.0d0 456.0d0)
|
||||
|
||||
(deftest incf-pointer.1
|
||||
(let ((ptr (null-pointer)))
|
||||
(incf-pointer ptr)
|
||||
(pointer-address ptr))
|
||||
1)
|
||||
|
||||
(deftest incf-pointer.2
|
||||
(let ((ptr (null-pointer)))
|
||||
(incf-pointer ptr 42)
|
||||
(pointer-address ptr))
|
||||
42)
|
||||
|
||||
(deftest pointerp.1
|
||||
(values
|
||||
(pointerp (null-pointer))
|
||||
(null-pointer-p (null-pointer))
|
||||
(typep (null-pointer) 'foreign-pointer))
|
||||
t t t)
|
||||
|
||||
(deftest pointerp.2
|
||||
(let ((p (make-pointer #xFEFF)))
|
||||
(values
|
||||
(pointerp p)
|
||||
(typep p 'foreign-pointer)))
|
||||
t t)
|
||||
|
||||
(deftest pointerp.3
|
||||
(pointerp 'not-a-pointer)
|
||||
nil)
|
||||
|
||||
(deftest pointerp.4
|
||||
(pointerp 42)
|
||||
nil)
|
||||
|
||||
(deftest pointerp.5
|
||||
(pointerp 0)
|
||||
nil)
|
||||
|
||||
(deftest pointerp.6
|
||||
(pointerp nil)
|
||||
nil)
|
||||
|
||||
(deftest mem-ref.setf.1
|
||||
(with-foreign-object (p :char)
|
||||
(setf (mem-ref p :char) 42))
|
||||
42)
|
||||
|
||||
(define-foreign-type int+1 ()
|
||||
()
|
||||
(:actual-type :int)
|
||||
(:simple-parser int+1))
|
||||
|
||||
(defmethod translate-to-foreign (value (type int+1))
|
||||
(1+ value))
|
||||
|
||||
(defmethod translate-from-foreign (value (type int+1))
|
||||
(1+ value))
|
||||
|
||||
(deftest mem-ref.setf.2
|
||||
(with-foreign-object (p 'int+1)
|
||||
(values (setf (mem-ref p 'int+1) 42)
|
||||
(mem-ref p 'int+1)))
|
||||
42 ; should this be 43?
|
||||
44)
|
||||
|
||||
(deftest pointer-eq.non-pointers.1
|
||||
(expecting-error (pointer-eq 1 2))
|
||||
:error)
|
||||
|
||||
(deftest pointer-eq.non-pointers.2
|
||||
(expecting-error (pointer-eq 'a 'b))
|
||||
:error)
|
||||
|
||||
(deftest null-pointer-p.non-pointer.1
|
||||
(expecting-error (null-pointer-p 'not-a-pointer))
|
||||
:error)
|
||||
|
||||
(deftest null-pointer-p.non-pointer.2
|
||||
(expecting-error (null-pointer-p 0))
|
||||
:error)
|
||||
|
||||
(deftest null-pointer-p.non-pointer.3
|
||||
(expecting-error (null-pointer-p nil))
|
||||
:error)
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; misc-types.lisp --- Various tests on the type system.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(defcfun ("my_strdup" strdup) :string+ptr (str :string))
|
||||
|
||||
(defcfun ("my_strfree" strfree) :void (str :pointer))
|
||||
|
||||
(deftest misc-types.string+ptr
|
||||
(destructuring-bind (string pointer)
|
||||
(strdup "foo")
|
||||
(strfree pointer)
|
||||
string)
|
||||
"foo")
|
||||
|
||||
#-(and)
|
||||
(deftest misc-types.string+ptr.ub8
|
||||
(destructuring-bind (string pointer)
|
||||
(strdup (make-array 3 :element-type '(unsigned-byte 8)
|
||||
:initial-contents (map 'list #'char-code "foo")))
|
||||
(strfree pointer)
|
||||
string)
|
||||
"foo")
|
||||
|
||||
#-(and)
|
||||
(deftest misc-types.string.ub8.1
|
||||
(let ((array (make-array 7 :element-type '(unsigned-byte 8)
|
||||
:initial-contents '(84 117 114 97 110 103 97))))
|
||||
(with-foreign-string (foreign-string array)
|
||||
(foreign-string-to-lisp foreign-string)))
|
||||
"Turanga")
|
||||
|
||||
#-(and)
|
||||
(deftest misc-types.string.ub8.2
|
||||
(let ((str (foreign-string-alloc
|
||||
(make-array 7 :element-type '(unsigned-byte 8)
|
||||
:initial-contents '(84 117 114 97 110 103 97)))))
|
||||
(prog1 (foreign-string-to-lisp str)
|
||||
(foreign-string-free str)))
|
||||
"Turanga")
|
||||
|
||||
(defcfun "equalequal" :boolean
|
||||
(a (:boolean :int))
|
||||
(b (:boolean :unsigned-int)))
|
||||
|
||||
(defcfun "bool_and" (:boolean :char)
|
||||
(a (:boolean :unsigned-char))
|
||||
(b (:boolean :char)))
|
||||
|
||||
(defcfun "bool_xor" (:boolean :unsigned-long)
|
||||
(a (:boolean :long))
|
||||
(b (:boolean :unsigned-long)))
|
||||
|
||||
(deftest misc-types.boolean.1
|
||||
(list (equalequal nil nil)
|
||||
(equalequal t t)
|
||||
(equalequal t 23)
|
||||
(bool-and 'a 'b)
|
||||
(bool-and "foo" nil)
|
||||
(bool-xor t nil)
|
||||
(bool-xor nil nil))
|
||||
(t t t t nil t nil))
|
||||
|
||||
(defcfun "sizeof_bool" :unsigned-int)
|
||||
|
||||
(deftest misc-types.sizeof.bool
|
||||
(eql (sizeof-bool) (foreign-type-size :bool))
|
||||
t)
|
||||
|
||||
(defcfun "bool_to_unsigned" :unsigned-int
|
||||
(b :bool))
|
||||
|
||||
(defcfun "unsigned_to_bool" :bool
|
||||
(u :unsigned-int))
|
||||
|
||||
(deftest misc-types.bool.convert-to-foreign.mem
|
||||
(loop for v in '(nil t)
|
||||
collect
|
||||
(with-foreign-object (b :bool)
|
||||
(setf (mem-ref b :bool) v)
|
||||
(mem-ref b #.(cffi::canonicalize-foreign-type :bool))))
|
||||
(0 1))
|
||||
|
||||
(deftest misc-types.bool.convert-to-foreign.call
|
||||
(mapcar #'bool-to-unsigned '(nil t))
|
||||
(0 1))
|
||||
|
||||
(deftest misc-types.bool.convert-from-foreign.mem
|
||||
(loop for v in '(0 1 42)
|
||||
collect
|
||||
(with-foreign-object (b :bool)
|
||||
(setf (mem-ref b #.(cffi::canonicalize-foreign-type :bool)) v)
|
||||
(mem-ref b :bool)))
|
||||
(nil t t))
|
||||
|
||||
(deftest misc-types.bool.convert-from-foreign.call
|
||||
(mapcar #'unsigned-to-bool '(0 1 42))
|
||||
(nil t t))
|
||||
|
||||
;;; Regression test: boolean type only worked with canonicalized
|
||||
;;; built-in integer types. Should work for any type that canonicalizes
|
||||
;;; to a built-in integer type.
|
||||
(defctype int-for-bool :int)
|
||||
(defcfun ("equalequal" equalequal2) :boolean
|
||||
(a (:boolean int-for-bool))
|
||||
(b (:boolean :uint)))
|
||||
|
||||
(deftest misc-types.boolean.2
|
||||
(equalequal2 nil t)
|
||||
nil)
|
||||
|
||||
(defctype my-string :string+ptr)
|
||||
|
||||
(defun funkify (str)
|
||||
(concatenate 'string "MORE " (string-upcase str)))
|
||||
|
||||
(defun 3rd-person (value)
|
||||
(list (concatenate 'string "Strdup says: " (first value))
|
||||
(second value)))
|
||||
|
||||
;; (defctype funky-string
|
||||
;; (:wrapper my-string
|
||||
;; :to-c #'funkify
|
||||
;; :from-c (lambda (value)
|
||||
;; (list
|
||||
;; (concatenate 'string "Strdup says: "
|
||||
;; (first value))
|
||||
;; (second value))))
|
||||
;; "A useful type.")
|
||||
|
||||
(defctype funky-string (:wrapper my-string :to-c funkify :from-c 3rd-person))
|
||||
|
||||
(defcfun ("my_strdup" funky-strdup) funky-string
|
||||
(str funky-string))
|
||||
|
||||
(deftest misc-types.wrapper
|
||||
(destructuring-bind (string ptr)
|
||||
(funky-strdup "code")
|
||||
(strfree ptr)
|
||||
string)
|
||||
"Strdup says: MORE CODE")
|
||||
|
||||
(deftest misc-types.sized-ints
|
||||
(mapcar #'foreign-type-size
|
||||
'(:int8 :uint8 :int16 :uint16 :int32 :uint32 :int64 :uint64))
|
||||
(1 1 2 2 4 4 8 8))
|
||||
|
||||
(define-foreign-type error-error ()
|
||||
()
|
||||
(:actual-type :int)
|
||||
(:simple-parser error-error))
|
||||
|
||||
(defmethod translate-to-foreign (value (type error-error))
|
||||
(declare (ignore value))
|
||||
(error "translate-to-foreign invoked."))
|
||||
|
||||
(defmethod translate-from-foreign (value (type error-error))
|
||||
(declare (ignore value))
|
||||
(error "translate-from-foreign invoked."))
|
||||
|
||||
(eval-when (:load-toplevel :compile-toplevel :execute)
|
||||
(defmethod expand-to-foreign (value (type error-error))
|
||||
value)
|
||||
|
||||
(defmethod expand-from-foreign (value (type error-error))
|
||||
value))
|
||||
|
||||
(defcfun ("abs" expand-abs) error-error
|
||||
(n error-error))
|
||||
|
||||
(defcvar ("var_int" *expand-var-int*) error-error)
|
||||
|
||||
(defcfun ("expect_int_sum" expand-expect-int-sum) :boolean
|
||||
(cb :pointer))
|
||||
|
||||
(defcallback expand-int-sum error-error ((x error-error) (y error-error))
|
||||
(+ x y))
|
||||
|
||||
;;; Ensure that macroexpansion-time translators are called where this
|
||||
;;; is guaranteed (defcfun, defcvar, foreign-funcall and defcallback)
|
||||
(deftest misc-types.expand.1
|
||||
(expand-abs -1)
|
||||
1)
|
||||
|
||||
#-cffi-sys::no-foreign-funcall
|
||||
(deftest misc-types.expand.2
|
||||
(foreign-funcall "abs" error-error -1 error-error)
|
||||
1)
|
||||
|
||||
(deftest misc-types.expand.3
|
||||
(let ((old (mem-ref (get-var-pointer '*expand-var-int*) :int)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setf *expand-var-int* 42)
|
||||
*expand-var-int*)
|
||||
(setf (mem-ref (get-var-pointer '*expand-var-int*) :int) old)))
|
||||
42)
|
||||
|
||||
(deftest misc-types.expand.4
|
||||
(expand-expect-int-sum (callback expand-int-sum))
|
||||
t)
|
||||
|
||||
(define-foreign-type translate-tracker ()
|
||||
()
|
||||
(:actual-type :int)
|
||||
(:simple-parser translate-tracker))
|
||||
|
||||
(declaim (special .fto-called.))
|
||||
|
||||
(defmethod free-translated-object (value (type translate-tracker) param)
|
||||
(declare (ignore value param))
|
||||
(setf .fto-called. t))
|
||||
|
||||
(define-foreign-type expand-tracker ()
|
||||
()
|
||||
(:actual-type :int)
|
||||
(:simple-parser expand-tracker))
|
||||
|
||||
(defmethod free-translated-object (value (type expand-tracker) param)
|
||||
(declare (ignore value param))
|
||||
(setf .fto-called. t))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(defmethod expand-to-foreign (value (type expand-tracker))
|
||||
(declare (ignore value))
|
||||
(call-next-method)))
|
||||
|
||||
(defcfun ("abs" ttracker-abs) :int
|
||||
(n translate-tracker))
|
||||
|
||||
(defcfun ("abs" etracker-abs) :int
|
||||
(n expand-tracker))
|
||||
|
||||
;; free-translated-object must be called when there is no etf
|
||||
(deftest misc-types.expand.5
|
||||
(let ((.fto-called. nil))
|
||||
(ttracker-abs -1)
|
||||
.fto-called.)
|
||||
t)
|
||||
|
||||
;; free-translated-object must be called when there is an etf, but
|
||||
;; they answer *runtime-translator-form*
|
||||
(deftest misc-types.expand.6
|
||||
(let ((.fto-called. nil))
|
||||
(etracker-abs -1)
|
||||
.fto-called.)
|
||||
t)
|
||||
|
||||
(define-foreign-type misc-type.expand.7 ()
|
||||
()
|
||||
(:actual-type :int)
|
||||
(:simple-parser misc-type.expand.7))
|
||||
|
||||
(defmethod translate-to-foreign (value (type misc-type.expand.7))
|
||||
(values value 'second-value))
|
||||
|
||||
;; Auxiliary function to test CONVERT-TO-FOREIGN's compiler macro.
|
||||
(defun misc-type.expand.7-aux ()
|
||||
(convert-to-foreign "foo" 'misc-type.expand.7))
|
||||
|
||||
;; Checking that expand-to-foreign doesn't ignore the second value of
|
||||
;; translate-to-foreign.
|
||||
(deftest misc-type.expand.7
|
||||
(misc-type.expand.7-aux)
|
||||
"foo" second-value)
|
||||
|
||||
;; Like MISC-TYPE.EXPAND.7 but doesn't depend on compiler macros
|
||||
;; kicking in.
|
||||
(deftest misc-type.expand.8
|
||||
(eval (expand-to-foreign "foo" (cffi::parse-type 'misc-type.expand.7)))
|
||||
"foo" second-value)
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; misc.lisp --- Miscellaneous tests.
|
||||
;;;
|
||||
;;; Copyright (C) 2006, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
;;;# foreign-symbol-pointer tests
|
||||
|
||||
;;; This might be useful for some libraries that compare function
|
||||
;;; pointers. http://thread.gmane.org/gmane.lisp.cffi.devel/694
|
||||
(defcfun "compare_against_abs" :boolean (p :pointer))
|
||||
|
||||
(deftest foreign-symbol-pointer.1
|
||||
(compare-against-abs (foreign-symbol-pointer "abs"))
|
||||
t)
|
||||
|
||||
(defcfun "compare_against_xpto_fun" :boolean (p :pointer))
|
||||
|
||||
(deftest foreign-symbol-pointer.2
|
||||
(compare-against-xpto-fun (foreign-symbol-pointer "xpto_fun"))
|
||||
t)
|
||||
|
||||
;;;# Library tests
|
||||
;;;
|
||||
;;; Need to figure out a way to test this. CLISP, for instance, will
|
||||
;;; automatically reopen the foreign-library when we call a foreign
|
||||
;;; function so we can't test CLOSE-FOREIGN-LIBRARY this way.
|
||||
;;;
|
||||
;;; IIRC, GCC has some extensions to have code run when a library is
|
||||
;;; loaded and stuff like that. That could work.
|
||||
|
||||
#||
|
||||
#-(and ecl (not dffi))
|
||||
(deftest library.close.2
|
||||
(unwind-protect
|
||||
(progn
|
||||
(close-foreign-library 'libtest)
|
||||
(ignore-errors (my-sqrtf 16.0)))
|
||||
(load-test-libraries))
|
||||
nil)
|
||||
|
||||
#-(or (and ecl (not dffi))
|
||||
cffi-sys::flat-namespace
|
||||
cffi-sys::no-foreign-funcall)
|
||||
(deftest library.close.2
|
||||
(unwind-protect
|
||||
(values
|
||||
(foreign-funcall ("ns_function" :library libtest) :boolean)
|
||||
(close-foreign-library 'libtest)
|
||||
(foreign-funcall "ns_function" :boolean)
|
||||
(close-foreign-library 'libtest2)
|
||||
(close-foreign-library 'libtest2)
|
||||
(ignore-errors (foreign-funcall "ns_function" :boolean)))
|
||||
(load-test-libraries))
|
||||
t t nil t nil nil)
|
||||
||#
|
||||
|
||||
(deftest library.error.1
|
||||
(handler-case (load-foreign-library "libdoesnotexistimsure")
|
||||
(load-foreign-library-error () 'error))
|
||||
error)
|
||||
|
||||
(define-foreign-library pseudo-library
|
||||
(t pseudo-library-spec))
|
||||
|
||||
;;; RT: T clause was being handled as :T by FEATUREP.
|
||||
;;;
|
||||
;;; We might want to export (and clean up) the API used in this test
|
||||
;;; when the need arises.
|
||||
(deftest library.t-clause
|
||||
(eq (cffi::foreign-library-spec
|
||||
(cffi::get-foreign-library 'pseudo-library))
|
||||
'pseudo-library-spec)
|
||||
t)
|
||||
|
||||
(define-foreign-library library-with-pathname
|
||||
(t #p"libdoesnotexistimsure"))
|
||||
|
||||
;;; RT: we were mishandling pathnames within libraries. (lp#1720626)
|
||||
(deftest library.error.2
|
||||
(handler-case (load-foreign-library 'library-with-pathname)
|
||||
(load-foreign-library-error () 'error))
|
||||
error)
|
||||
|
||||
(deftest library.error.3
|
||||
(handler-case (load-foreign-library #p"libdoesnotexistimsure")
|
||||
(load-foreign-library-error () 'error))
|
||||
error)
|
||||
|
||||
;;;# Shareable Byte Vector Tests
|
||||
|
||||
#+ecl
|
||||
(mapc (lambda (x) (pushnew x rt::*expected-failures*))
|
||||
'(shareable-vector.1 shareable-vector.2))
|
||||
|
||||
(deftest shareable-vector.1
|
||||
(let ((vector (cffi-sys::make-shareable-byte-vector 5)))
|
||||
(cffi::with-pointer-to-vector-data (pointer vector)
|
||||
(strcpy pointer "xpto"))
|
||||
vector)
|
||||
#(120 112 116 111 0))
|
||||
|
||||
(deftest shareable-vector.2
|
||||
(block nil
|
||||
(let ((vector (cffi-sys::make-shareable-byte-vector 5)))
|
||||
(cffi::with-pointer-to-vector-data (pointer vector)
|
||||
(strcpy pointer "xpto")
|
||||
(return vector))))
|
||||
#(120 112 116 111 0))
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; package.lisp --- CFFI-TESTS package definition.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, James Bielman <jamesjb@jamesjb.com>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cl-user)
|
||||
|
||||
(defpackage #:cffi-tests
|
||||
(:use #:cl #:cffi #:cffi-sys #:regression-test)
|
||||
(:export #:do-tests #:run-cffi-tests #:run-all-cffi-tests)
|
||||
(:shadow #:deftest))
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; random-tester.lisp --- Random test generator.
|
||||
;;;
|
||||
;;; Copyright (C) 2006, Luis Oliveira <loliveira(@)common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
;;; This code was used to generate the C and Lisp source code for
|
||||
;;; the CALLBACKS.BFF.[12] and DEFCFUN.BFF.[12] tests.
|
||||
;;;
|
||||
;;; The original idea was to test all combinations of argument types
|
||||
;;; but obviously as soon as you do the maths that it's not quite
|
||||
;;; feasable for more that 4 or 5 arguments.
|
||||
;;;
|
||||
;;; TODO: actually run random tests, ie compile/load/run the tests
|
||||
;;; this code can generate.
|
||||
|
||||
(defpackage #:cffi-random-tester
|
||||
(:use #:cl #:cffi #:alexandria #:regression-test))
|
||||
(in-package #:cffi-random-tester)
|
||||
|
||||
(defstruct (c-type (:conc-name type-))
|
||||
keyword
|
||||
name
|
||||
abbrev
|
||||
min
|
||||
max)
|
||||
|
||||
(defparameter +types+
|
||||
(mapcar (lambda (type)
|
||||
(let ((keyword (first type))
|
||||
(name (second type)))
|
||||
(multiple-value-bind (min max)
|
||||
;; assume we can represent an integer in the range
|
||||
;; [-2^16 2^16-1] in a float/double without causing
|
||||
;; rounding errors (probably a lame assumption)
|
||||
(let ((type-size (if (or (eq keyword :float)
|
||||
(eq keyword :double))
|
||||
16
|
||||
(* 8 (foreign-type-size keyword)))))
|
||||
(if (or (eql (char name 0) #\u) (eq keyword :pointer))
|
||||
(values 0 (1- (expt 2 type-size)))
|
||||
(values (- (expt 2 (1- type-size)))
|
||||
(1- (expt 2 (1- type-size))))))
|
||||
(make-c-type :keyword keyword :name name :abbrev (third type)
|
||||
:min min :max max))))
|
||||
'((:char "char" "c")
|
||||
(:unsigned-char "unsigned char" "uc")
|
||||
(:short "short" "s")
|
||||
(:unsigned-short "unsigned short" "us")
|
||||
(:int "int" "i")
|
||||
(:unsigned-int "unsigned int" "ui")
|
||||
(:long "long" "l")
|
||||
(:unsigned-long "unsigned long" "ul")
|
||||
(:float "float" "f")
|
||||
(:double "double" "d")
|
||||
(:pointer "void*" "p")
|
||||
(:long-long "long long" "ll")
|
||||
(:unsigned-long-long "unsigned long long" "ull"))))
|
||||
|
||||
(defun find-type (keyword)
|
||||
(find keyword +types+ :key #'type-keyword))
|
||||
|
||||
(defun n-random-types (n)
|
||||
(loop repeat n collect (nth (random (length +types+)) +types+)))
|
||||
|
||||
;;; same as above, without the long long types
|
||||
(defun n-random-types-no-ll (n)
|
||||
(loop repeat n collect (nth (random (- (length +types+) 2)) +types+)))
|
||||
|
||||
(defun random-range (x y)
|
||||
(+ x (random (+ (- y x) 2))))
|
||||
|
||||
(defun random-sum (rettype arg-types)
|
||||
"Returns a list of integers that fit in the respective types in the
|
||||
ARG-TYPES list and whose sum fits in RETTYPE."
|
||||
(loop with sum = 0
|
||||
for type in arg-types
|
||||
for x = (random-range (max (- (type-min rettype) sum) (type-min type))
|
||||
(min (- (type-max rettype) sum) (type-max type)))
|
||||
do (incf sum x)
|
||||
collect x))
|
||||
|
||||
(defun combinations (n items)
|
||||
(let ((combs '()))
|
||||
(labels ((rec (n accum)
|
||||
(if (= n 0)
|
||||
(push accum combs)
|
||||
(loop for item in items
|
||||
do (rec (1- n) (cons item accum))))))
|
||||
(rec n '())
|
||||
combs)))
|
||||
|
||||
(defun function-name (rettype arg-types)
|
||||
(format nil "sum_~A_~{_~A~}"
|
||||
(type-abbrev rettype)
|
||||
(mapcar #'type-abbrev arg-types)))
|
||||
|
||||
(defun c-function (rettype arg-types)
|
||||
(let ((args (loop for type in arg-types and i from 1
|
||||
collect (list (type-name type) (format nil "a~A" i)))))
|
||||
(format t "DLLEXPORT ~A ~A(~{~{~A ~A~}~^, ~})~%~
|
||||
{ return ~A(~A) ~{~A~^ + ~}~A; }"
|
||||
(type-name rettype) (function-name rettype arg-types) args
|
||||
(if (eq (type-keyword rettype) :pointer)
|
||||
"(void *)((unsigned int)("
|
||||
"")
|
||||
(type-name rettype)
|
||||
(loop for arg-pair in args collect
|
||||
(format nil "~A~A~A"
|
||||
(cond ((string= (first arg-pair) "void*")
|
||||
"(unsigned int) ")
|
||||
((or (string= (first arg-pair) "double")
|
||||
(string= (first arg-pair) "float"))
|
||||
"((int) ")
|
||||
(t ""))
|
||||
(second arg-pair)
|
||||
(if (member (first arg-pair)
|
||||
'("void*" "double" "float")
|
||||
:test #'string=)
|
||||
")"
|
||||
"")))
|
||||
(if (eq (type-keyword rettype) :pointer) "))" ""))))
|
||||
|
||||
(defun c-callback (rettype arg-types args)
|
||||
(format t "DLLEXPORT ~A call_~A(~A (*func)(~{~A~^, ~}~^))~%~
|
||||
{ return func(~{~A~^, ~}); }"
|
||||
(type-name rettype) (function-name rettype arg-types)
|
||||
(type-name rettype) (mapcar #'type-name arg-types)
|
||||
(loop for type in arg-types and value in args collect
|
||||
(format nil "~A~A"
|
||||
(if (eq (type-keyword type) :pointer)
|
||||
"(void *) "
|
||||
"")
|
||||
value))))
|
||||
|
||||
;;; (output-c-code #p"generated.c" 3 5)
|
||||
(defun output-c-code (file min max)
|
||||
(with-open-file (stream file :direction :output :if-exists :error)
|
||||
(let ((*standard-output* stream))
|
||||
(format t "/* automatically generated functions and callbacks */~%~%")
|
||||
(loop for n from min upto max do
|
||||
(format t "/* ~A args */" (1- n))
|
||||
(loop for comb in (combinations n +types+) do
|
||||
(terpri) (c-function (car comb) (cdr comb))
|
||||
(terpri) (c-callback (car comb) (cdr comb)))))))
|
||||
|
||||
(defmacro with-conversion (type form)
|
||||
(case type
|
||||
(:double `(float ,form 1.0d0))
|
||||
(:float `(float ,form))
|
||||
(:pointer `(make-pointer ,form))
|
||||
(t form)))
|
||||
|
||||
(defun integer-conversion (type form)
|
||||
(case type
|
||||
((:double :float) `(values (floor ,form)))
|
||||
(:pointer `(pointer-address ,form))
|
||||
(t form)))
|
||||
|
||||
(defun gen-arg-values (rettype arg-types)
|
||||
(let ((numbers (random-sum rettype arg-types)))
|
||||
(values
|
||||
(reduce #'+ numbers)
|
||||
(loop for type in arg-types and n in numbers
|
||||
collect (case (type-keyword type)
|
||||
(:double (float n 1.0d0))
|
||||
(:float (float n))
|
||||
(:pointer `(make-pointer ,n))
|
||||
(t n))))))
|
||||
|
||||
(defun gen-function-test (rettype arg-types)
|
||||
(let* ((fun-name (function-name rettype arg-types))
|
||||
(fun-sym (cffi::lisp-function-name fun-name)))
|
||||
(multiple-value-bind (sum value-forms)
|
||||
(gen-arg-values rettype arg-types)
|
||||
`(progn
|
||||
(defcfun (,fun-name ,fun-sym) ,(type-keyword rettype)
|
||||
,@(loop for type in arg-types and i from 1 collect
|
||||
(list (symbolicate '#:a (format nil "~A" i))
|
||||
(type-keyword type))))
|
||||
(deftest ,(symbolicate '#:defcfun. fun-sym)
|
||||
,(integer-conversion (type-keyword rettype)
|
||||
`(,fun-sym ,@value-forms))
|
||||
,sum)))))
|
||||
|
||||
(defun gen-callback-test (rettype arg-types sum)
|
||||
(let* ((fname (function-name rettype arg-types))
|
||||
(cb-sym (cffi::lisp-function-name fname))
|
||||
(fun-name (concatenate 'string "call_" fname))
|
||||
(fun-sym (cffi::lisp-function-name fun-name))
|
||||
(arg-names (loop for i from 1 upto (length arg-types) collect
|
||||
(symbolicate '#:a (format nil "~A" i)))))
|
||||
`(progn
|
||||
(defcfun (,fun-name ,fun-sym) ,(type-keyword rettype) (cb :pointer))
|
||||
(defcallback ,cb-sym ,(type-keyword rettype)
|
||||
,(loop for type in arg-types and name in arg-names
|
||||
collect (list name (type-keyword type)))
|
||||
,(integer-conversion
|
||||
(type-keyword rettype)
|
||||
`(+ ,@(mapcar (lambda (tp n)
|
||||
(integer-conversion (type-keyword tp) n))
|
||||
arg-types arg-names))))
|
||||
(deftest ,(symbolicate '#:callbacks. cb-sym)
|
||||
,(integer-conversion (type-keyword rettype)
|
||||
`(,fun-sym (callback ,cb-sym)))
|
||||
,sum))))
|
||||
|
||||
(defun cb-test (&key no-long-long)
|
||||
(let* ((rettype (find-type (if no-long-long :long :long-long)))
|
||||
(arg-types (if no-long-long
|
||||
(n-random-types-no-ll 127)
|
||||
(n-random-types 127)))
|
||||
(args (random-sum rettype arg-types))
|
||||
(sum (reduce #'+ args)))
|
||||
(c-callback rettype arg-types args)
|
||||
(gen-callback-test rettype arg-types sum)))
|
||||
|
||||
;; (defmacro define-function-and-callback-tests (min max)
|
||||
;; `(progn
|
||||
;; ,@(loop for n from min upto max appending
|
||||
;; (loop for comb in (combinations n +types+)
|
||||
;; collect (gen-function-test (car comb) (cdr comb))
|
||||
;; collect (gen-callback-test (car comb) (cdr comb))))))
|
||||
|
||||
;; (define-function-and-callback-tests 3 5)
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; run-tests.lisp --- Simple script to run the unit tests.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, James Bielman <jamesjb@jamesjb.com>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cl-user)
|
||||
|
||||
(setf *load-verbose* nil *compile-verbose* nil *compile-print* nil)
|
||||
#+cmucl (setf ext:*gc-verbose* nil)
|
||||
|
||||
(require "asdf")
|
||||
|
||||
(format t "~&;;; -------- Running tests in ~A --------~%"
|
||||
(uiop:implementation-identifier))
|
||||
|
||||
(asdf:load-system "cffi-tests" :verbose nil)
|
||||
(asdf:test-system "cffi-tests")
|
||||
|
||||
(terpri)
|
||||
(force-output)
|
||||
|
||||
(uiop:quit)
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; strings.lisp --- Tests for foreign string conversion.
|
||||
;;;
|
||||
;;; Copyright (C) 2005, James Bielman <jamesjb@jamesjb.com>
|
||||
;;; Copyright (C) 2007, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
;;;# Foreign String Conversion Tests
|
||||
;;;
|
||||
;;; With the implementation of encoding support, there are a lot of
|
||||
;;; things that can go wrong with foreign string conversions. This is
|
||||
;;; a start at defining tests for strings and encoding conversion, but
|
||||
;;; there needs to be a lot more.
|
||||
|
||||
(babel:enable-sharp-backslash-syntax)
|
||||
|
||||
;;; *ASCII-TEST-STRING* contains the characters in the ASCII character
|
||||
;;; set that we will convert to a foreign string and check against
|
||||
;;; *ASCII-TEST-BYTES*. We don't bother with control characters.
|
||||
;;;
|
||||
;;; FIXME: It would probably be good to move these tables into files
|
||||
;;; in "tests/", especially if we ever want to get fancier and have
|
||||
;;; tests for more encodings.
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(defparameter *ascii-test-string*
|
||||
(concatenate 'string " !\"#$%&'()*+,-./0123456789:;"
|
||||
"<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]"
|
||||
"^_`abcdefghijklmnopqrstuvwxyz{|}~")))
|
||||
|
||||
;;; *ASCII-TEST-BYTES* contains the expected ASCII encoded values
|
||||
;;; for each character in *ASCII-TEST-STRING*.
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(defparameter *ascii-test-bytes*
|
||||
(let ((vector (make-array 95 :element-type '(unsigned-byte 8))))
|
||||
(loop for i from 0
|
||||
for code from 32 below 127
|
||||
do (setf (aref vector i) code)
|
||||
finally (return vector)))))
|
||||
|
||||
;;; Test basic consistency converting a string to and from Lisp using
|
||||
;;; the default encoding.
|
||||
(deftest string.conversion.basic
|
||||
(with-foreign-string (s *ascii-test-string*)
|
||||
(foreign-string-to-lisp s))
|
||||
#.*ascii-test-string* 95)
|
||||
|
||||
(deftest string.conversion.basic.2
|
||||
(with-foreign-string ((ptr size) "123" :null-terminated-p nil)
|
||||
(values (foreign-string-to-lisp ptr :count 3) size))
|
||||
"123" 3)
|
||||
|
||||
;;; Ensure that conversion of *ASCII-TEST-STRING* to a foreign buffer
|
||||
;;; and back preserves ASCII encoding.
|
||||
(deftest string.encoding.ascii
|
||||
(with-foreign-string (s *ascii-test-string* :encoding :ascii)
|
||||
(let ((vector (make-array 95 :element-type '(unsigned-byte 8))))
|
||||
(loop for i from 0 below (length vector)
|
||||
do (setf (aref vector i) (mem-ref s :unsigned-char i)))
|
||||
vector))
|
||||
#.*ascii-test-bytes*)
|
||||
|
||||
;;; FIXME: bogus test. We need support for BOM or UTF-16{BE,LE}.
|
||||
(pushnew 'string.encoding.utf-16.basic rtest::*expected-failures*)
|
||||
|
||||
;;; Test UTF-16 conversion of a string back and forth. Tests proper
|
||||
;;; null terminator handling for wide character strings and ensures no
|
||||
;;; byte order marks are added. (Why no BOM? --luis)
|
||||
;;;
|
||||
;;; FIXME: an identical test using :UTF-16 wouldn't work because on
|
||||
;;; little-endian architectures, :UTF-16 defaults to little-endian
|
||||
;;; when writing and big-endian on reading because the BOM is
|
||||
;;; suppressed.
|
||||
#-babel::8-bit-chars
|
||||
(progn
|
||||
(deftest string.encoding.utf-16le.basic
|
||||
(with-foreign-string (s *ascii-test-string* :encoding :utf-16le)
|
||||
(foreign-string-to-lisp s :encoding :utf-16le))
|
||||
#.*ascii-test-string* 190)
|
||||
|
||||
(deftest string.encoding.utf-16be.basic
|
||||
(with-foreign-string (s *ascii-test-string* :encoding :utf-16be)
|
||||
(foreign-string-to-lisp s :encoding :utf-16be))
|
||||
#.*ascii-test-string* 190))
|
||||
|
||||
;;; Ensure that writing a long string into a short buffer does not
|
||||
;;; attempt to write beyond the edge of the buffer, and that the
|
||||
;;; resulting string is still null terminated.
|
||||
(deftest string.short-write.1
|
||||
(with-foreign-pointer (buf 6)
|
||||
(setf (mem-ref buf :unsigned-char 5) 70)
|
||||
(lisp-string-to-foreign "ABCDE" buf 5 :encoding :ascii)
|
||||
(values (mem-ref buf :unsigned-char 4)
|
||||
(mem-ref buf :unsigned-char 5)))
|
||||
0 70)
|
||||
|
||||
#-babel::8-bit-chars
|
||||
(deftest string.encoding.utf-8.basic
|
||||
(with-foreign-pointer (buf 7 size)
|
||||
(let ((string (concatenate 'babel:unicode-string
|
||||
'(#\u03bb #\u00e3 #\u03bb))))
|
||||
(lisp-string-to-foreign string buf size :encoding :utf-8)
|
||||
(loop for i from 0 below size
|
||||
collect (mem-ref buf :unsigned-char i))))
|
||||
(206 187 195 163 206 187 0))
|
||||
|
||||
(defparameter *basic-latin-alphabet* "abcdefghijklmnopqrstuvwxyz")
|
||||
|
||||
(deftest string.encodings.all.basic
|
||||
(let (failed)
|
||||
;;; FIXME: UTF-{32,16} and friends fail due to lack of BOM. See
|
||||
;;; STRING.ENCODING.UTF-16.BASIC for more details.
|
||||
(dolist (encoding (remove-if (lambda (x)
|
||||
(member x '(:utf-32 :utf-16 :ucs-2)))
|
||||
(babel:list-character-encodings)))
|
||||
;; (format t "Testing ~S~%" encoding)
|
||||
(with-foreign-string (ptr *basic-latin-alphabet* :encoding encoding)
|
||||
(let ((string (foreign-string-to-lisp ptr :encoding encoding)))
|
||||
;; (format t " got ~S~%" string)
|
||||
(unless (string= *basic-latin-alphabet* string)
|
||||
(push encoding failed)))))
|
||||
failed)
|
||||
nil)
|
||||
|
||||
;;; rt: make sure *default-foreign-enconding* binds to a keyword
|
||||
(deftest string.encodings.default
|
||||
(keywordp *default-foreign-encoding*)
|
||||
t)
|
||||
|
|
@ -0,0 +1,705 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; struct.lisp --- Foreign structure type tests.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, James Bielman <jamesjb@jamesjb.com>
|
||||
;;; Copyright (C) 2005-2011, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(defcstruct timeval
|
||||
(tv-secs :long)
|
||||
(tv-usecs :long))
|
||||
|
||||
(defparameter *timeval-size* (* 2 (max (foreign-type-size :long)
|
||||
(foreign-type-alignment :long))))
|
||||
|
||||
;;;# Basic Structure Tests
|
||||
|
||||
(deftest struct.1
|
||||
(- (foreign-type-size 'timeval) *timeval-size*)
|
||||
0)
|
||||
|
||||
(deftest struct.2
|
||||
(with-foreign-object (tv 'timeval)
|
||||
(setf (foreign-slot-value tv 'timeval 'tv-secs) 0)
|
||||
(setf (foreign-slot-value tv 'timeval 'tv-usecs) 1)
|
||||
(values (foreign-slot-value tv 'timeval 'tv-secs)
|
||||
(foreign-slot-value tv 'timeval 'tv-usecs)))
|
||||
0 1)
|
||||
|
||||
(deftest struct.3
|
||||
(with-foreign-object (tv 'timeval)
|
||||
(with-foreign-slots ((tv-secs tv-usecs) tv timeval)
|
||||
(setf tv-secs 100 tv-usecs 200)
|
||||
(values tv-secs tv-usecs)))
|
||||
100 200)
|
||||
|
||||
;; regression test: accessing a struct through a typedef
|
||||
|
||||
(defctype xpto (:struct timeval))
|
||||
|
||||
(deftest struct.4
|
||||
(with-foreign-object (tv 'xpto)
|
||||
(setf (foreign-slot-value tv 'xpto 'tv-usecs) 1)
|
||||
(values (foreign-slot-value tv 'xpto 'tv-usecs)
|
||||
(foreign-slot-value tv 'timeval 'tv-usecs)))
|
||||
1 1)
|
||||
|
||||
(deftest struct.names
|
||||
(sort (foreign-slot-names 'xpto) #'<
|
||||
:key (lambda (x) (foreign-slot-offset 'xpto x)))
|
||||
(tv-secs tv-usecs))
|
||||
|
||||
;; regression test: compiler macro not quoting the type in the
|
||||
;; resulting mem-ref form. The compiler macro on foreign-slot-value
|
||||
;; is not guaranteed to be expanded though.
|
||||
|
||||
(defctype my-int :int)
|
||||
(defcstruct s5 (a my-int))
|
||||
|
||||
(deftest struct.5
|
||||
(with-foreign-object (s 's5)
|
||||
(setf (foreign-slot-value s 's5 'a) 42)
|
||||
(foreign-slot-value s 's5 'a))
|
||||
42)
|
||||
|
||||
;;;# Structs with type translators
|
||||
|
||||
(defcstruct struct-string
|
||||
(s :string))
|
||||
|
||||
(deftest struct.string.1
|
||||
(with-foreign-object (ptr 'struct-string)
|
||||
(with-foreign-slots ((s) ptr struct-string)
|
||||
(setf s "So long and thanks for all the fish!")
|
||||
s))
|
||||
"So long and thanks for all the fish!")
|
||||
|
||||
(deftest struct.string.2
|
||||
(with-foreign-object (ptr 'struct-string)
|
||||
(setf (foreign-slot-value ptr 'struct-string 's) "Cha")
|
||||
(foreign-slot-value ptr 'struct-string 's))
|
||||
"Cha")
|
||||
|
||||
;;;# Structure Alignment Tests
|
||||
;;;
|
||||
;;; See libtest.c and types.lisp for some comments about alignments.
|
||||
|
||||
(defcstruct s-ch
|
||||
(a-char :char))
|
||||
|
||||
(defctype s-ch (:struct s-ch))
|
||||
|
||||
(defcstruct s-s-ch
|
||||
(another-char :char)
|
||||
(a-s-ch s-ch))
|
||||
|
||||
(defctype s-s-ch (:struct s-s-ch))
|
||||
|
||||
(defcvar "the_s_s_ch" s-s-ch)
|
||||
|
||||
(deftest struct.alignment.1
|
||||
(list 'a-char (foreign-slot-value
|
||||
(foreign-slot-pointer *the-s-s-ch* 's-s-ch 'a-s-ch)
|
||||
's-ch 'a-char)
|
||||
'another-char (foreign-slot-value *the-s-s-ch* 's-s-ch 'another-char))
|
||||
(a-char 1 another-char 2))
|
||||
|
||||
|
||||
(defcstruct s-short
|
||||
(a-char :char)
|
||||
(another-char :char)
|
||||
(a-short :short))
|
||||
|
||||
(defctype s-short (:struct s-short))
|
||||
|
||||
(defcstruct s-s-short
|
||||
(yet-another-char :char)
|
||||
(a-s-short s-short))
|
||||
|
||||
(defctype s-s-short (:struct s-s-short))
|
||||
|
||||
(defcvar "the_s_s_short" s-s-short)
|
||||
|
||||
(deftest struct.alignment.2
|
||||
(with-foreign-slots ((yet-another-char a-s-short) *the-s-s-short* s-s-short)
|
||||
(with-foreign-slots ((a-char another-char a-short) a-s-short s-short)
|
||||
(list 'a-char a-char
|
||||
'another-char another-char
|
||||
'a-short a-short
|
||||
'yet-another-char yet-another-char)))
|
||||
(a-char 1 another-char 2 a-short 3 yet-another-char 4))
|
||||
|
||||
|
||||
(defcstruct s-double
|
||||
(a-char :char)
|
||||
(a-double :double)
|
||||
(another-char :char))
|
||||
|
||||
(defctype s-double (:struct s-double))
|
||||
|
||||
(defcstruct s-s-double
|
||||
(yet-another-char :char)
|
||||
(a-s-double s-double)
|
||||
(a-short :short))
|
||||
|
||||
(defctype s-s-double (:struct s-s-double))
|
||||
|
||||
(defcvar "the_s_s_double" s-s-double)
|
||||
|
||||
(deftest struct.alignment.3
|
||||
(with-foreign-slots
|
||||
((yet-another-char a-s-double a-short) *the-s-s-double* s-s-double)
|
||||
(with-foreign-slots ((a-char a-double another-char) a-s-double s-double)
|
||||
(list 'a-char a-char
|
||||
'a-double a-double
|
||||
'another-char another-char
|
||||
'yet-another-char yet-another-char
|
||||
'a-short a-short)))
|
||||
(a-char 1 a-double 2.0d0 another-char 3 yet-another-char 4 a-short 5))
|
||||
|
||||
|
||||
(defcstruct s-s-s-double
|
||||
(another-short :short)
|
||||
(a-s-s-double s-s-double)
|
||||
(last-char :char))
|
||||
|
||||
(defctype s-s-s-double (:struct s-s-s-double))
|
||||
|
||||
(defcvar "the_s_s_s_double" s-s-s-double)
|
||||
|
||||
(deftest struct.alignment.4
|
||||
(with-foreign-slots
|
||||
((another-short a-s-s-double last-char) *the-s-s-s-double* s-s-s-double)
|
||||
(with-foreign-slots
|
||||
((yet-another-char a-s-double a-short) a-s-s-double s-s-double)
|
||||
(with-foreign-slots ((a-char a-double another-char) a-s-double s-double)
|
||||
(list 'a-char a-char
|
||||
'a-double a-double
|
||||
'another-char another-char
|
||||
'yet-another-char yet-another-char
|
||||
'a-short a-short
|
||||
'another-short another-short
|
||||
'last-char last-char))))
|
||||
(a-char 1 a-double 2.0d0 another-char 3 yet-another-char 4 a-short 5
|
||||
another-short 6 last-char 7))
|
||||
|
||||
|
||||
(defcstruct s-double2
|
||||
(a-double :double)
|
||||
(a-short :short))
|
||||
|
||||
(defctype s-double2 (:struct s-double2))
|
||||
|
||||
(defcstruct s-s-double2
|
||||
(a-char :char)
|
||||
(a-s-double2 s-double2)
|
||||
(another-short :short))
|
||||
|
||||
(defctype s-s-double2 (:struct s-s-double2))
|
||||
|
||||
(defcvar "the_s_s_double2" s-s-double2)
|
||||
|
||||
(deftest struct.alignment.5
|
||||
(with-foreign-slots
|
||||
((a-char a-s-double2 another-short) *the-s-s-double2* s-s-double2)
|
||||
(with-foreign-slots ((a-double a-short) a-s-double2 s-double2)
|
||||
(list 'a-double a-double
|
||||
'a-short a-short
|
||||
'a-char a-char
|
||||
'another-short another-short)))
|
||||
(a-double 1.0d0 a-short 2 a-char 3 another-short 4))
|
||||
|
||||
(defcstruct s-long-long
|
||||
(a-long-long :long-long)
|
||||
(a-short :short))
|
||||
|
||||
(defctype s-long-long (:struct s-long-long))
|
||||
|
||||
(defcstruct s-s-long-long
|
||||
(a-char :char)
|
||||
(a-s-long-long s-long-long)
|
||||
(another-short :short))
|
||||
|
||||
(defctype s-s-long-long (:struct s-s-long-long))
|
||||
|
||||
(defcvar "the_s_s_long_long" s-s-long-long)
|
||||
|
||||
(deftest struct.alignment.6
|
||||
(with-foreign-slots
|
||||
((a-char a-s-long-long another-short) *the-s-s-long-long* s-s-long-long)
|
||||
(with-foreign-slots ((a-long-long a-short) a-s-long-long s-long-long)
|
||||
(list 'a-long-long a-long-long
|
||||
'a-short a-short
|
||||
'a-char a-char
|
||||
'another-short another-short)))
|
||||
(a-long-long 1 a-short 2 a-char 3 another-short 4))
|
||||
|
||||
(defcstruct s-s-double3
|
||||
(a-s-double2 s-double2)
|
||||
(another-short :short))
|
||||
|
||||
(defctype s-s-double3 (:struct s-s-double3))
|
||||
|
||||
(defcstruct s-s-s-double3
|
||||
(a-s-s-double3 s-s-double3)
|
||||
(a-char :char))
|
||||
|
||||
(defctype s-s-s-double3 (:struct s-s-s-double3))
|
||||
|
||||
(defcvar "the_s_s_s_double3" s-s-s-double3)
|
||||
|
||||
(deftest struct.alignment.7
|
||||
(with-foreign-slots ((a-s-s-double3 a-char) *the-s-s-s-double3* s-s-s-double3)
|
||||
(with-foreign-slots ((a-s-double2 another-short) a-s-s-double3 s-s-double3)
|
||||
(with-foreign-slots ((a-double a-short) a-s-double2 s-double2)
|
||||
(list 'a-double a-double
|
||||
'a-short a-short
|
||||
'another-short another-short
|
||||
'a-char a-char))))
|
||||
(a-double 1.0d0 a-short 2 another-short 3 a-char 4))
|
||||
|
||||
|
||||
(defcstruct empty-struct)
|
||||
|
||||
(defctype empty-struct (:struct empty-struct))
|
||||
|
||||
(defcstruct with-empty-struct
|
||||
(foo empty-struct)
|
||||
(an-int :int))
|
||||
|
||||
;; commented out this test because an empty struct is not valid/standard C
|
||||
;; left the struct declarations anyway because they should be handled
|
||||
;; gracefuly anyway.
|
||||
|
||||
; (defcvar "the_with_empty_struct" with-empty-struct)
|
||||
;
|
||||
; (deftest struct.alignment.5
|
||||
; (with-foreign-slots ((foo an-int) *the-with-empty-struct* with-empty-struct)
|
||||
; an-int)
|
||||
; 42)
|
||||
|
||||
|
||||
;; regression test, setf-ing nested foreign-slot-value forms
|
||||
;; the setf expander used to return a bogus getter
|
||||
|
||||
(defcstruct s1
|
||||
(an-int :int))
|
||||
|
||||
(defctype s1 (:struct s1))
|
||||
|
||||
(defcstruct s2
|
||||
(an-s1 s1))
|
||||
|
||||
(defctype s2 (:struct s2))
|
||||
|
||||
(deftest struct.nested-setf
|
||||
(with-foreign-object (an-s2 's2)
|
||||
(setf (foreign-slot-value (foreign-slot-value an-s2 's2 'an-s1)
|
||||
's1 'an-int)
|
||||
1984)
|
||||
(foreign-slot-value (foreign-slot-value an-s2 's2 'an-s1)
|
||||
's1 'an-int))
|
||||
1984)
|
||||
|
||||
;; regression test, some Lisps were returning 4 instead of 8 for
|
||||
;; (foreign-type-alignment :unsigned-long-long) on darwin/ppc32
|
||||
|
||||
(defcstruct s-unsigned-long-long
|
||||
(an-unsigned-long-long :unsigned-long-long)
|
||||
(a-short :short))
|
||||
|
||||
(defctype s-unsigned-long-long (:struct s-unsigned-long-long))
|
||||
|
||||
(defcstruct s-s-unsigned-long-long
|
||||
(a-char :char)
|
||||
(a-s-unsigned-long-long s-unsigned-long-long)
|
||||
(another-short :short))
|
||||
|
||||
(defctype s-s-unsigned-long-long (:struct s-s-unsigned-long-long))
|
||||
|
||||
(defcvar "the_s_s_unsigned_long_long" s-s-unsigned-long-long)
|
||||
|
||||
(deftest struct.alignment.8
|
||||
(with-foreign-slots
|
||||
((a-char a-s-unsigned-long-long another-short)
|
||||
*the-s-s-unsigned-long-long* s-s-unsigned-long-long)
|
||||
(with-foreign-slots ((an-unsigned-long-long a-short)
|
||||
a-s-unsigned-long-long s-unsigned-long-long)
|
||||
(list 'an-unsigned-long-long an-unsigned-long-long
|
||||
'a-short a-short
|
||||
'a-char a-char
|
||||
'another-short another-short)))
|
||||
(an-unsigned-long-long 1 a-short 2 a-char 3 another-short 4))
|
||||
|
||||
;;;# C Struct Wrappers
|
||||
|
||||
(define-c-struct-wrapper timeval ())
|
||||
|
||||
(define-c-struct-wrapper (timeval2 (:struct timeval)) ()
|
||||
(tv-secs))
|
||||
|
||||
(defmacro with-example-timeval (var &body body)
|
||||
`(with-foreign-object (,var 'timeval)
|
||||
(with-foreign-slots ((tv-secs tv-usecs) ,var timeval)
|
||||
(setf tv-secs 42 tv-usecs 1984)
|
||||
,@body)))
|
||||
|
||||
(deftest struct-wrapper.1
|
||||
(with-example-timeval ptr
|
||||
(let ((obj (make-instance 'timeval :pointer ptr)))
|
||||
(values (timeval-tv-secs obj)
|
||||
(timeval-tv-usecs obj))))
|
||||
42 1984)
|
||||
|
||||
(deftest struct-wrapper.2
|
||||
(with-example-timeval ptr
|
||||
(let ((obj (make-instance 'timeval2 :pointer ptr)))
|
||||
(timeval2-tv-secs obj)))
|
||||
42)
|
||||
|
||||
;;;# Structures as Values
|
||||
|
||||
(defcstruct (struct-pair :class pair)
|
||||
(a :int)
|
||||
(b :int))
|
||||
|
||||
(defctype struct-pair-typedef1 (:struct struct-pair))
|
||||
(defctype struct-pair-typedef2 (:pointer (:struct struct-pair)))
|
||||
|
||||
(deftest struct.unparse.1
|
||||
(mapcar (alexandria:compose #'cffi::unparse-type #'cffi::parse-type)
|
||||
'(struct-pair
|
||||
(:struct struct-pair)
|
||||
struct-pair-typedef1
|
||||
struct-pair-typedef2))
|
||||
(struct-pair
|
||||
(:struct struct-pair)
|
||||
struct-pair-typedef1
|
||||
struct-pair-typedef2))
|
||||
|
||||
(deftest struct.canonicalize.1
|
||||
(mapcar #'cffi::canonicalize-foreign-type
|
||||
'(struct-pair
|
||||
(:struct struct-pair)
|
||||
struct-pair-typedef1
|
||||
struct-pair-typedef2))
|
||||
(:pointer
|
||||
(:struct struct-pair)
|
||||
(:struct struct-pair)
|
||||
:pointer))
|
||||
|
||||
(deftest struct.canonicalize.2
|
||||
(mapcar #'cffi::canonicalize-foreign-type
|
||||
'(struct-pair
|
||||
(:struct struct-pair)
|
||||
struct-pair-typedef1
|
||||
struct-pair-typedef2))
|
||||
(:pointer
|
||||
(:struct struct-pair)
|
||||
(:struct struct-pair)
|
||||
:pointer))
|
||||
|
||||
(defmethod translate-from-foreign (pointer (type pair))
|
||||
(with-foreign-slots ((a b) pointer (:struct struct-pair))
|
||||
(cons a b)))
|
||||
|
||||
(defmethod translate-into-foreign-memory (object (type pair) pointer)
|
||||
(with-foreign-slots ((a b) pointer (:struct struct-pair))
|
||||
(setf a (car object)
|
||||
b (cdr object))))
|
||||
|
||||
(defmethod translate-to-foreign (object (type pair))
|
||||
(let ((p (foreign-alloc '(:struct struct-pair))))
|
||||
(translate-into-foreign-memory object type p)
|
||||
(values p t)))
|
||||
|
||||
(defmethod free-translated-object (pointer (type pair) freep)
|
||||
(when freep
|
||||
(foreign-free pointer)))
|
||||
|
||||
(deftest struct-values.translation.1
|
||||
(multiple-value-bind (p freep)
|
||||
(convert-to-foreign '(1 . 2) 'struct-pair)
|
||||
(assert freep)
|
||||
(unwind-protect
|
||||
(convert-from-foreign p 'struct-pair)
|
||||
(free-converted-object p 'struct-pair freep)))
|
||||
(1 . 2))
|
||||
|
||||
(defcfun "pair_pointer_sum" :int
|
||||
(p (:pointer (:struct struct-pair))))
|
||||
|
||||
#+#:pointer-translation-not-yet-implemented
|
||||
(deftest struct-values.translation.2
|
||||
(pair-pointer-sum '(1 . 2))
|
||||
3)
|
||||
|
||||
;;; should the return type be something along the lines of
|
||||
;;; (:pointer (:struct pair) :free t)?
|
||||
;;; LMH: error on ":free t" option?
|
||||
(defcfun "alloc_pair" (:pointer (:struct struct-pair))
|
||||
(a :int)
|
||||
(b :int))
|
||||
|
||||
;; bogus: doesn't free() pointer.
|
||||
#+#:pointer-translation-not-yet-implemented
|
||||
(deftest struct-values.translation.3
|
||||
(alloc-pair 1 2)
|
||||
(1 . 2))
|
||||
|
||||
(deftest struct-values.translation.mem-ref.1
|
||||
(with-foreign-object (p '(:struct struct-pair))
|
||||
(setf (mem-ref p '(:struct struct-pair)) '(1 . 2))
|
||||
(with-foreign-slots ((a b) p (:struct struct-pair))
|
||||
(values (mem-ref p '(:struct struct-pair))
|
||||
a
|
||||
b)))
|
||||
(1 . 2)
|
||||
1
|
||||
2)
|
||||
|
||||
(deftest struct-values.translation.mem-aref.1
|
||||
(with-foreign-object (p '(:struct struct-pair) 2)
|
||||
(setf (mem-aref p '(:struct struct-pair) 0) '(1 . 2)
|
||||
(mem-aref p '(:struct struct-pair) 1) '(3 . 4))
|
||||
(values (mem-aref p '(:struct struct-pair) 0)
|
||||
(mem-aref p '(:struct struct-pair) 1)))
|
||||
(1 . 2)
|
||||
(3 . 4))
|
||||
|
||||
(defcstruct (struct-pair-default-translate :class pair-default)
|
||||
(a :int)
|
||||
(b :int))
|
||||
|
||||
(deftest struct-values-default.translation.mem-ref.1
|
||||
(with-foreign-object (p '(:struct struct-pair-default-translate))
|
||||
(setf (mem-ref p '(:struct struct-pair-default-translate)) '(a 1 b 2))
|
||||
(with-foreign-slots ((a b) p (:struct struct-pair-default-translate))
|
||||
(let ((plist (mem-ref p '(:struct struct-pair-default-translate))))
|
||||
(values (getf plist 'a)
|
||||
(getf plist 'b)
|
||||
a
|
||||
b))))
|
||||
1
|
||||
2
|
||||
1
|
||||
2)
|
||||
|
||||
(defcstruct (struct-pair+double :class pair+double)
|
||||
(pr (:struct struct-pair-default-translate))
|
||||
(dbl :double))
|
||||
|
||||
(deftest struct-values-default.translation.mem-ref.2
|
||||
(with-foreign-object (p '(:struct struct-pair+double))
|
||||
(setf (mem-ref p '(:struct struct-pair+double)) '(pr (a 4 b 5) dbl 2.5d0))
|
||||
(with-foreign-slots ((pr dbl) p (:struct struct-pair+double))
|
||||
(let ((plist (mem-ref p '(:struct struct-pair+double))))
|
||||
(values (getf (getf plist 'pr) 'a)
|
||||
(getf (getf plist 'pr) 'b)
|
||||
(getf plist 'dbl)))))
|
||||
4
|
||||
5
|
||||
2.5d0)
|
||||
|
||||
(defcstruct (struct-pair+1 :class pair+1)
|
||||
(p (:pointer (:struct struct-pair)))
|
||||
(c :int))
|
||||
|
||||
(defctype struct-pair+1 (:struct struct-pair+1))
|
||||
|
||||
(defmethod translate-from-foreign (pointer (type pair+1))
|
||||
(with-foreign-slots ((p c) pointer struct-pair+1)
|
||||
(cons p c)))
|
||||
|
||||
(defmethod translate-into-foreign-memory (object (type pair+1) pointer)
|
||||
(with-foreign-slots ((c) pointer struct-pair+1)
|
||||
(convert-into-foreign-memory (car object)
|
||||
'struct-pair
|
||||
(foreign-slot-pointer pointer
|
||||
'struct-pair+1
|
||||
'p))
|
||||
(setf c (cdr object))))
|
||||
|
||||
(defmethod translate-to-foreign (object (type pair+1))
|
||||
(let ((p (foreign-alloc 'struct-pair+1)))
|
||||
(translate-into-foreign-memory object type p)
|
||||
(values p t)))
|
||||
|
||||
(defmethod free-translated-object (pointer (type pair+1) freep)
|
||||
(when freep
|
||||
(foreign-free pointer)))
|
||||
|
||||
#+#:pointer-translation-not-yet-implemented
|
||||
(deftest struct-values.translation.ppo.1
|
||||
(multiple-value-bind (p freep)
|
||||
(convert-to-foreign '((1 . 2) . 3) 'struct-pair+1)
|
||||
(assert freep)
|
||||
(unwind-protect
|
||||
(convert-from-foreign p 'struct-pair+1)
|
||||
(free-converted-object p 'struct-pair+1 freep)))
|
||||
((1 . 2) . 3))
|
||||
|
||||
#+#:unimplemented
|
||||
(defcfun "pair_plus_one_sum" :int
|
||||
(p (:struct pair+1)))
|
||||
|
||||
(defcfun "pair_plus_one_pointer_sum" :int
|
||||
(p (:pointer (:struct struct-pair+1))))
|
||||
|
||||
#+#:pointer-translation-not-yet-implemented
|
||||
(deftest struct-values.translation.ppo.2
|
||||
(pair-plus-one-pointer-sum '((1 . 2) . 3))
|
||||
6)
|
||||
|
||||
#+#:unimplemented
|
||||
(defcfun "make_pair_plus_one" (:struct pair+1)
|
||||
(a :int)
|
||||
(b :int)
|
||||
(c :int))
|
||||
|
||||
(defcfun "alloc_pair_plus_one" struct-pair+1
|
||||
(a :int)
|
||||
(b :int)
|
||||
(c :int))
|
||||
|
||||
;; bogus: doesn't free() pointer.
|
||||
#+#:pointer-translation-not-yet-implemented
|
||||
(deftest struct-values.translation.ppo.3
|
||||
(alloc-pair-plus-one 1 2 3)
|
||||
((1 . 2) . 3))
|
||||
|
||||
#+#:unimplemented
|
||||
(defcfun "pair_sum" :int
|
||||
(p (:struct pair)))
|
||||
|
||||
#+#:unimplemented
|
||||
(defcfun "make_pair" (:struct pair)
|
||||
(a :int)
|
||||
(b :int))
|
||||
|
||||
#|| ; TODO: load cffi-libffi for these tests to work.
|
||||
(deftest struct-values.fn.1
|
||||
(with-foreign-object (p '(:struct pair))
|
||||
(with-foreign-slots ((a b) p (:struct pair))
|
||||
(setf a -1 b 2)
|
||||
(pair-sum p)))
|
||||
1)
|
||||
|
||||
(deftest struct-values.fn.2
|
||||
(pair-sum '(3 . 5))
|
||||
8)
|
||||
|
||||
(deftest struct-values.fn.3
|
||||
(with-foreign-object (p '(:struct pair))
|
||||
(make-pair 7 11 :result-pointer p)
|
||||
(with-foreign-slots ((a b) p (:struct pair))
|
||||
(cons a b)))
|
||||
(7 . 11))
|
||||
|
||||
(deftest struct-values.fn.4
|
||||
(make-pair 13 17)
|
||||
(13 . 17))
|
||||
||#
|
||||
|
||||
(defcstruct single-byte-struct
|
||||
(a :uint8))
|
||||
|
||||
(deftest bare-struct-types.1
|
||||
(eql (foreign-type-size 'single-byte-struct)
|
||||
(foreign-type-size '(:struct single-byte-struct)))
|
||||
t)
|
||||
|
||||
(defctype single-byte-struct-alias (:struct single-byte-struct))
|
||||
|
||||
(deftest bare-struct-types.2
|
||||
(eql (foreign-type-size 'single-byte-struct-alias)
|
||||
(foreign-type-size '(:struct single-byte-struct)))
|
||||
t)
|
||||
|
||||
;;; Old-style access to inner structure fields.
|
||||
|
||||
(defcstruct inner-struct (x :int))
|
||||
(defcstruct old-style-outer (inner inner-struct))
|
||||
(defcstruct new-style-outer (inner (:struct inner-struct)))
|
||||
|
||||
(deftest old-style-struct-access
|
||||
(with-foreign-object (s '(:struct old-style-outer))
|
||||
(let ((inner-ptr (foreign-slot-pointer s 'old-style-outer 'inner)))
|
||||
(setf (foreign-slot-value inner-ptr 'inner-struct 'x) 42))
|
||||
(assert (pointerp (foreign-slot-value s 'old-style-outer 'inner)))
|
||||
(foreign-slot-value (foreign-slot-value s 'old-style-outer 'inner)
|
||||
'inner-struct 'x))
|
||||
42)
|
||||
|
||||
(deftest new-style-struct-access
|
||||
(with-foreign-object (s '(:struct new-style-outer))
|
||||
(let ((inner-ptr (foreign-slot-pointer s 'new-style-outer 'inner)))
|
||||
(setf (foreign-slot-value inner-ptr 'inner-struct 'x) 42))
|
||||
(foreign-slot-value s 'new-style-outer 'inner))
|
||||
(x 42))
|
||||
|
||||
;;; regression test: setting the value of aggregate slots.
|
||||
|
||||
(defcstruct aggregate-struct
|
||||
(x :int)
|
||||
(pair (:struct struct-pair))
|
||||
(y :int))
|
||||
|
||||
(deftest set-aggregate-struct-slot
|
||||
(with-foreign-objects ((pair-struct '(:struct struct-pair))
|
||||
(aggregate-struct '(:struct aggregate-struct)))
|
||||
(with-foreign-slots ((a b) pair-struct (:struct struct-pair))
|
||||
(setf a 1 b 2)
|
||||
(with-foreign-slots ((x pair y) aggregate-struct (:struct aggregate-struct))
|
||||
(setf x 42 y 42)
|
||||
(setf pair pair-struct)
|
||||
(values x pair y))))
|
||||
42
|
||||
(1 . 2)
|
||||
42)
|
||||
|
||||
;; TODO this needs to go through compile-file to exhibit the error
|
||||
;; ("don't know how to dump #<CFFI::AGGREGATE-STRUCT-SLOT>"), but
|
||||
;; there's no support for that, so let's leave it at toplevel here.
|
||||
(defcstruct (aggregate-struct.acc :conc-name acc-)
|
||||
(x :int)
|
||||
(pair (:struct struct-pair))
|
||||
(y :int))
|
||||
|
||||
(deftest set-aggregate-struct-slot.acc
|
||||
(with-foreign-objects ((pair-struct '(:struct struct-pair))
|
||||
(aggregate-struct '(:struct aggregate-struct)))
|
||||
(with-foreign-slots ((a b) pair-struct (:struct struct-pair))
|
||||
(setf a 1 b 2)
|
||||
(setf (acc-x aggregate-struct) 42)
|
||||
(setf (acc-y aggregate-struct) 42)
|
||||
(setf (acc-pair aggregate-struct) pair-struct)
|
||||
(values (acc-x aggregate-struct)
|
||||
(acc-pair aggregate-struct)
|
||||
(acc-y aggregate-struct))))
|
||||
42
|
||||
(1 . 2)
|
||||
42)
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; asdf.lisp --- CFFI-Grovel asdf support tests.
|
||||
;;;
|
||||
;;; Copyright (C) 2015, Luis Oliveira <loliveira@common-lisp.net>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
#.(when (cffi-toolchain::static-ops-enabled-p)
|
||||
'(deftest test-static-program
|
||||
(progn
|
||||
(asdf:operate :static-program-op :cffi-tests/example)
|
||||
(let ((program (asdf:output-file :static-program-op :cffi-tests/example)))
|
||||
(uiop:run-program `(,(native-namestring program) "1" "2 3") :output :lines)))
|
||||
("Arguments: 1 \"2 3\"" "hello, world!") nil 0))
|
||||
|
||||
(deftest test-asdf-load
|
||||
(progn
|
||||
(asdf:load-system :cffi-tests/example)
|
||||
(uiop:symbol-call :cffi-example :check-groveller))
|
||||
nil)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh -eux
|
||||
|
||||
for l in sbcl ; do # mkcl ecl clisp sbcl
|
||||
EX="$(cl-launch -l $l -sp cffi-toolchain -ip "(output-file :static-program-op :cffi-tests/example)")"
|
||||
rm -f $EX ; :
|
||||
cl-launch -l $l -sp cffi-toolchain -i "(operate :static-program-op :cffi-tests/example)"
|
||||
[ -f $EX ]
|
||||
[ "$($EX)" = "hello, world!" ]
|
||||
done
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
|
||||
;;;
|
||||
;;; union.lisp --- Tests on C unions.
|
||||
;;;
|
||||
;;; Copyright (C) 2005-2006, James Bielman <jamesjb@jamesjb.com>
|
||||
;;;
|
||||
;;; Permission is hereby granted, free of charge, to any person
|
||||
;;; obtaining a copy of this software and associated documentation
|
||||
;;; files (the "Software"), to deal in the Software without
|
||||
;;; restriction, including without limitation the rights to use, copy,
|
||||
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
;;; of the Software, and to permit persons to whom the Software is
|
||||
;;; furnished to do so, subject to the following conditions:
|
||||
;;;
|
||||
;;; The above copyright notice and this permission notice shall be
|
||||
;;; included in all copies or substantial portions of the Software.
|
||||
;;;
|
||||
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;;; DEALINGS IN THE SOFTWARE.
|
||||
;;;
|
||||
|
||||
(in-package #:cffi-tests)
|
||||
|
||||
(defcunion uint32-bytes
|
||||
(int-value :unsigned-int)
|
||||
(bytes :unsigned-char :count 4))
|
||||
|
||||
(defctype uint32-bytes (:union uint32-bytes))
|
||||
|
||||
(defun int-to-bytes (n)
|
||||
"Convert N to a list of bytes using a union."
|
||||
(with-foreign-object (obj 'uint32-bytes)
|
||||
(setf (foreign-slot-value obj 'uint32-bytes 'int-value) n)
|
||||
(loop for i from 0 below 4
|
||||
collect (mem-aref
|
||||
(foreign-slot-value obj 'uint32-bytes 'bytes)
|
||||
:unsigned-char i))))
|
||||
|
||||
(deftest union.1
|
||||
(let ((bytes (int-to-bytes #x12345678)))
|
||||
(cond ((equal bytes '(#x12 #x34 #x56 #x78))
|
||||
t)
|
||||
((equal bytes '(#x78 #x56 #x34 #x12))
|
||||
t)
|
||||
(t bytes)))
|
||||
t)
|
||||
Loading…
Add table
Add a link
Reference in a new issue