ffi-gsl.k (2064B)
1 ;; 2 ;; Dynamic FFI callback example. 3 ;; Interfacing GNU Scientific Library. 4 ;; 5 ;; struct gsl_function_struct { 6 ;; double (* function) (double x, void * params); 7 ;; void * params; 8 ;; }; 9 ;; typedef struct gsl_function_struct gsl_function ; 10 ;; 11 ;; int gsl_deriv_central (const gsl_function * f, double x, double h, double * result, double * abserr) 12 ;; 13 ;; (ffi-make-callback APPLICATIVE CALL-INTERFACE) creates a C callable 14 ;; function with interface CALL-INTERFACE and returns pointer 15 ;; to the entry point. The function will in turn call APPLICATIVE. 16 ;; 17 18 ($define! gsl (ffi-load-library "libgsl.so")) 19 ($define! abi "FFI_DEFAULT_ABI") 20 21 ($define! make-gsl-function 22 ($let 23 ( ((pointer-size alingment ref set!) (ffi-type-suite "pointer")) 24 (cif (ffi-make-call-interface abi "double" (list "double" "pointer"))) ) 25 ($lambda (f) 26 ($let 27 ( (gslf (make-bytevector (* 2 pointer-size)) ) 28 (aux ($lambda (x params) (f x)))) 29 (set! (list gslf 0) (ffi-make-callback aux cif)) 30 gslf)))) 31 32 ($define! gsl-deriv-central 33 ($let 34 ( (gsl_deriv_central (ffi-make-applicative gsl "gsl_deriv_central" 35 (ffi-make-call-interface abi "sint" (list "pointer" "double" "double" "pointer" "pointer")))) 36 ((double-size alingment ref set!) (ffi-type-suite "double"))) 37 ($lambda (f) 38 ($let 39 ((gslf (make-gsl-function f))) 40 ($lambda (x h) 41 ($let 42 ( (result (make-bytevector double-size)) 43 (abserr (make-bytevector double-size))) 44 (gsl_deriv_central gslf x h result abserr) 45 (list (ref result) (ref abserr)))))))) 46 47 (display "Testing gsl_deriv_central...") 48 (newline) 49 50 ($define! f 51 ($lambda (x) 52 (display (list "callback called with x = " x)) 53 (newline) 54 (+ (* 2.0 x x) 3.0))) 55 ($define! df (gsl-deriv-central f)) 56 57 (for-each 58 ($lambda (x) 59 ($let* 60 ( (fx (f x)) 61 ((dfx abserr) (df x 0.001))) 62 (for-each 63 display 64 (list "x = " x ", f(x) = " fx ", f'(x) = " dfx ", |error| <= " abserr)) 65 (newline))) 66 (list -1.0 0.0 1.0 2.0))