funcall.lisp - clic - Clic is an command line interactive client for gopher written in Common LISP
 (HTM) git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
       funcall.lisp (8245B)
       ---
            1 ;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
            2 ;;;
            3 ;;; funcall.lisp --- Tests function calling.
            4 ;;;
            5 ;;; Copyright (C) 2005-2006, James Bielman  <jamesjb@jamesjb.com>
            6 ;;; Copyright (C) 2005-2007, Luis Oliveira  <loliveira@common-lisp.net>
            7 ;;;
            8 ;;; Permission is hereby granted, free of charge, to any person
            9 ;;; obtaining a copy of this software and associated documentation
           10 ;;; files (the "Software"), to deal in the Software without
           11 ;;; restriction, including without limitation the rights to use, copy,
           12 ;;; modify, merge, publish, distribute, sublicense, and/or sell copies
           13 ;;; of the Software, and to permit persons to whom the Software is
           14 ;;; furnished to do so, subject to the following conditions:
           15 ;;;
           16 ;;; The above copyright notice and this permission notice shall be
           17 ;;; included in all copies or substantial portions of the Software.
           18 ;;;
           19 ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
           20 ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
           21 ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
           22 ;;; NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
           23 ;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
           24 ;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
           25 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
           26 ;;; DEALINGS IN THE SOFTWARE.
           27 ;;;
           28 
           29 (in-package #:cffi-tests)
           30 
           31 ;;;# Calling with Built-In C Types
           32 ;;;
           33 ;;; Tests calling standard C library functions both passing and
           34 ;;; returning each built-in type.
           35 
           36 ;;; Don't run these tests if the implementation does not support
           37 ;;; foreign-funcall.
           38 #-cffi-sys::no-foreign-funcall
           39 (progn
           40 
           41 (deftest funcall.char
           42     (foreign-funcall "toupper" :char (char-code #\a) :char)
           43   #.(char-code #\A))
           44 
           45 (deftest funcall.int.1
           46     (foreign-funcall "abs" :int -100 :int)
           47   100)
           48 
           49 (defun funcall-abs (n)
           50   (foreign-funcall "abs" :int n :int))
           51 
           52 ;;; regression test: lispworks's %foreign-funcall based on creating
           53 ;;; and caching foreign-funcallables at macro-expansion time.
           54 (deftest funcall.int.2
           55     (funcall-abs -42)
           56   42)
           57 
           58 (deftest funcall.long
           59     (foreign-funcall "labs" :long -131072 :long)
           60   131072)
           61 
           62 #-cffi-sys::no-long-long
           63 (deftest funcall.long-long
           64     (foreign-funcall "my_llabs" :long-long -9223372036854775807 :long-long)
           65   9223372036854775807)
           66 
           67 #-cffi-sys::no-long-long
           68 (deftest funcall.unsigned-long-long
           69     (let ((ullong-max (1- (expt 2 (* 8 (foreign-type-size :unsigned-long-long))))))
           70       (eql ullong-max
           71            (foreign-funcall "ullong" :unsigned-long-long ullong-max
           72                                      :unsigned-long-long)))
           73   t)
           74 
           75 (deftest funcall.float
           76     (foreign-funcall "my_sqrtf" :float 16.0 :float)
           77   4.0)
           78 
           79 (deftest funcall.double
           80     (foreign-funcall "sqrt" :double 36.0d0 :double)
           81   6.0d0)
           82 
           83 #+(and scl long-float)
           84 (deftest funcall.long-double
           85     (foreign-funcall "sqrtl" :long-double 36.0l0 :long-double)
           86   6.0l0)
           87 
           88 (deftest funcall.string.1
           89     (foreign-funcall "strlen" :string "Hello" :int)
           90   5)
           91 
           92 (deftest funcall.string.2
           93     (with-foreign-pointer-as-string (s 100)
           94       (setf (mem-ref s :char) 0)
           95       (foreign-funcall "strcpy" :pointer s :string "Hello" :pointer)
           96       (foreign-funcall "strcat" :pointer s :string ", world!" :pointer))
           97   "Hello, world!")
           98 
           99 (deftest funcall.string.3
          100     (with-foreign-pointer (ptr 100)
          101       (lisp-string-to-foreign "Hello, " ptr 8)
          102       (foreign-funcall "strcat" :pointer ptr :string "world!" :string))
          103   "Hello, world!")
          104 
          105 ;;;# Calling Varargs Functions
          106 
          107 (deftest funcall.varargs.nostdlib
          108     (foreign-funcall-varargs
          109      "sum_double_arbitrary" (:int 26)
          110      :double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
          111      :double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
          112      :double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
          113      :double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
          114      :double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
          115      :double 3.14d0 :double 3.14d0 :double 3.14d0 :double 3.14d0
          116      :double 3.14d0 :double 3.14d0
          117      :double)
          118   81.64d0)
          119 
          120 ;; The CHAR argument must be passed as :INT because chars are promoted
          121 ;; to ints when passed as variable arguments.
          122 (deftest funcall.varargs.char
          123     (with-foreign-pointer-as-string (s 100)
          124       (setf (mem-ref s :char) 0)
          125       (foreign-funcall-varargs
          126        "sprintf" (:pointer s :string "%c") :int 65 :int))
          127   "A")
          128 
          129 (deftest funcall.varargs.int
          130     (with-foreign-pointer-as-string (s 100)
          131       (setf (mem-ref s :char) 0)
          132       (foreign-funcall-varargs
          133        "sprintf" (:pointer s :string "%d") :int 1000 :int))
          134   "1000")
          135 
          136 (deftest funcall.varargs.long
          137     (with-foreign-pointer-as-string (s 100)
          138       (setf (mem-ref s :char) 0)
          139       (foreign-funcall-varargs
          140        "sprintf" (:pointer s :string "%ld")
          141        :long 131072 :int))
          142   "131072")
          143 
          144 ;;; There is no FUNCALL.VARARGS.FLOAT as floats are promoted to double
          145 ;;; when passed as variable arguments.  Currently this fails in SBCL
          146 ;;; and CMU CL on Darwin/ppc.
          147 (deftest funcall.varargs.double
          148     (with-foreign-pointer-as-string (s 100)
          149       (setf (mem-ref s :char) 0)
          150       (foreign-funcall-varargs
          151        "sprintf" (:pointer s :string "%.2f") :double (coerce pi 'double-float) :int))
          152   "3.14")
          153 
          154 #+(and scl long-float)
          155 (deftest funcall.varargs.long-double
          156     (with-foreign-pointer-as-string (s 100)
          157       (setf (mem-ref s :char) 0)
          158       (foreign-funcall-varargs
          159        "sprintf" :pointer s :string "%.2Lf" :long-double pi :int))
          160   "3.14")
          161 
          162 (deftest funcall.varargs.string
          163     (with-foreign-pointer-as-string (s 100)
          164       (setf (mem-ref s :char) 0)
          165       (foreign-funcall-varargs
          166        "sprintf" (:pointer s :string "%s, %s!") :string "Hello" :string "world" :int))
          167   "Hello, world!")
          168 
          169 ;;; See DEFCFUN.DOUBLE26.
          170 (deftest funcall.double26
          171     (foreign-funcall "sum_double26"
          172                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          173                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          174                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          175                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          176                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          177                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          178                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          179                      :double 3.14d0 :double 3.14d0 :double 3.14d0
          180                      :double 3.14d0 :double 3.14d0 :double)
          181   81.64d0)
          182 
          183 ;;; See DEFCFUN.FLOAT26.
          184 (deftest funcall.float26
          185     (foreign-funcall "sum_float26"
          186                      :float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
          187                      :float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
          188                      :float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
          189                      :float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
          190                      :float 5.0 :float 5.0 :float 5.0 :float 5.0 :float 5.0
          191                      :float 5.0 :float)
          192   130.0)
          193 
          194 ;;; Funcalling a pointer.
          195 (deftest funcall.f-s-p.1
          196     (foreign-funcall-pointer (foreign-symbol-pointer "abs") nil :int -42 :int)
          197   42)
          198 
          199 ;;;# Namespaces
          200 
          201 #-cffi-sys::flat-namespace
          202 (deftest funcall.namespace.1
          203     (values (foreign-funcall ("ns_function" :library libtest) :boolean)
          204             (foreign-funcall ("ns_function" :library libtest2) :boolean))
          205   t nil)
          206 
          207 ;;;# stdcall
          208 
          209 #+(and x86 windows (not cffi-sys::no-stdcall))
          210 (deftest funcall.stdcall.1
          211     (flet ((fun ()
          212              (foreign-funcall ("stdcall_fun@12" :convention :stdcall)
          213                               :int 1 :int 2 :int 3 :int)))
          214       (loop repeat 100 do (fun)
          215             finally (return (fun))))
          216   6)
          217 
          218 ;;; RT: NIL arguments are skipped
          219 
          220 (defvar *nil-skipped*)
          221 
          222 (define-foreign-type check-nil-skip-type ()
          223   ()
          224   (:actual-type :pointer)
          225   (:simple-parser check-nil-skip-type))
          226 
          227 (defmethod expand-to-foreign (val (type check-nil-skip-type))
          228   (declare (ignore val))
          229   (setf *nil-skipped* nil)
          230   (null-pointer))
          231 
          232 (deftest funcall.nil-skip
          233     (let ((*nil-skipped* t))
          234       (compile nil '(lambda ()
          235                      (foreign-funcall "abs" check-nil-skip-type nil)))
          236       *nil-skipped*)
          237   nil)
          238 
          239 ;;; RT: CLISP returns NIL instead of a null-pointer
          240 
          241 (deftest funcall.pointer-not-nil
          242     (not (null (foreign-funcall "strchr" :string "" :int 1 :pointer)))
          243   t)
          244 
          245 ) ;; #-cffi-sys::no-foreign-funcall