Hello,
i want to use the GSL spline functionallity from within SBCL using the CFFI interface. So far i can do the "simple" functions returning pointers and/or values like the BESSEL function for example.
Now i 'am trying to setup an interface for the spline function but cannot manage to handle the "gsl_interp_cpline" pointer in lisp correctly. I did copy the needed parts here for simplicity:
/***************** gsl_types.h ************************/ <snip> # define GSL_VAR extern <snap> /***************** gsl_interp.h ***********************/ /* evaluation accelerator */ typedef struct { size_t cache; /* cache of index */ size_t miss_count; /* keep statistics */ size_t hit_count; } gsl_interp_accel;
/* interpolation object type */ typedef struct { const char * name; unsigned int min_size; void * (*alloc) (size_t size); int (*init) (void *, const double xa[], const double ya[], size_t size); int (*eval) (const void *, const double xa[], const double ya[], size_t size, double x, gsl_interp_accel *, double * y); int (*eval_deriv) (const void *, const double xa[], const double ya[], size_t size, double x, gsl_interp_accel *, double * y_p); int (*eval_deriv2) (const void *, const double xa[], const double ya[], size_t size, double x, gsl_interp_accel *, double * y_pp); int (*eval_integ) (const void *, const double xa[], const double ya[], size_t size, gsl_interp_accel *, double a, double b, double * result); void (*free) (void *);
} gsl_interp_type;
/* general interpolation object */ typedef struct { const gsl_interp_type * type; double xmin; double xmax; size_t size; void * state; } gsl_interp;
/* available types */ GSL_VAR const gsl_interp_type * gsl_interp_cspline;
gsl_interp_accel * gsl_interp_accel_alloc(void);
/********************** gsl_spline.h *********************************/ /* general interpolation object */
typedef struct { gsl_interp * interp; double * x; double * y; size_t size; } gsl_spline;
gsl_spline * gsl_spline_alloc(const gsl_interp_type * T, size_t size);
/********************* example.c **************************************/ <snip> gsl_interp_accel *acc = gsl_interp_accel_alloc (); gsl_spline *spline = gsl_spline_alloc (gsl_interp_cspline, 10); <snap> /*********************************************************************/
My lisp translation so far:
(defpackage :cffi-user (:use :common-lisp :cffi)) (in-package :cffi-user)
(pushnew #P"/usr/local/lib/" *foreign-library-directories* :test #'equal)
(define-foreign-library libgslcblas (:unix (:or "libgslcblas.so.0.0.0" "libgslcblas.so.0")) (t (:default "libgslcblas"))) (use-foreign-library libgslcblas)
(define-foreign-library libgsl (:unix (:or "libgsl.so.0.9.0" "libgsl.so.0")) (t (:default "libgsl"))) (use-foreign-library libgsl)
;;;; just to test the interface (defcfun "gsl_sf_bessel_J0" :double (x :double)) (format t "~A~%" (gsl-sf-bessel-J0 5d0)) ;;;; ok so far
(defcfun "gsl_interp_accel_alloc" :void) (defparameter *gsl-int-acc-alloc* (gsl-interp-accel-alloc)) ;;;; looks ok so far
(defctype gsl-cspline :pointer) <--- trouble
(defcfun "gsl_spline_alloc" :pointer (ptr :pointer) (n :int)) (defparameter *gsl-spline-alloc* (gsl-spline-alloc gsl-cspline 10))
My problem is that i cannot set this typed struc pointer "gsl_interp_cpline" correctly. Memory allocation ? What is the "magic" trick here ?
Heiko
Heiko Schroeter schroete@iup.physik.uni-bremen.de writes:
/* available types */ GSL_VAR const gsl_interp_type * gsl_interp_cspline;
(defctype gsl-cspline :pointer) <--- trouble
(defcfun "gsl_spline_alloc" :pointer (ptr :pointer) (n :int)) (defparameter *gsl-spline-alloc* (gsl-spline-alloc gsl-cspline 10))
It looks like "gsl_interp_cspline" is a global variable, not a type, so you probably want to be doing something like:
(defcvar "gsl_interp_cspline" :pointer)
That should define a symbol macro *GSL-INTERP-CSPLINE* that will get the value of that C variable as a foreign pointer (I must admit, it seems a little weird to me to name the symbol macro with the special variable naming convention, since it's not actually special...)
James
James Bielman <jamesjb <at> jamesjb.com> writes:
/* available types */ GSL_VAR const gsl_interp_type * gsl_interp_cspline;
It looks like "gsl_interp_cspline" is a global variable, not a type, so you probably want to be doing something like:
(defcvar "gsl_interp_cspline" :pointer)
That should define a symbol macro *GSL-INTERP-CSPLINE* that will get the value of that C variable as a foreign pointer (I must admit, it seems a little weird to me to name the symbol macro with the special variable naming convention, since it's not actually special...)
James
This seems to work ! Thanks a lot. A quick and manual hack as a test is here (a bit ugly, but just for a start...)
(unless (find-package 'cffi) (asdf:oos 'asdf:load-op :cffi))
(defpackage :cffi-user (:use :common-lisp :cffi)) (in-package :cffi-user)
(pushnew #P"/usr/local/lib/" *foreign-library-directories* :test #'equal)
(define-foreign-library libgslcblas (:unix (:or "libgslcblas.so.0.0.0" "libgslcblas.so.0")) (t (:default "libgslcblas"))) (use-foreign-library libgslcblas)
(define-foreign-library libgsl (:unix (:or "libgsl.so.0.9.0" "libgsl.so.0")) (t (:default "libgsl"))) (use-foreign-library libgsl)
;;;; ;;;(defcfun "gsl_sf_bessel_J0" :double (x :double)) ;;;(time (format t "~A~%" (gsl-sf-bessel-J0 5d0)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; declare stuff (defcfun "gsl_interp_accel_alloc" :pointer)
(defcvar "gsl_interp_cspline" :pointer) (defcfun "gsl_spline_alloc" :pointer (ptr :pointer) (n :int))
(defcfun "gsl_spline_init" :int (ptr :pointer) (x :pointer) (y :pointer) (n :int))
(defcfun "gsl_spline_eval" :double (spla :pointer) (xi :double) (acca :pointer))
(defcfun "gsl_spline_free" :void (ptr :pointer))
(defcfun "gsl_interp_accel_free" :void (ptr :pointer))
;;; Main Starts here (defparameter *gsl-int-acc-alloc* (gsl-interp-accel-alloc)) (defparameter *gsl-spline-alloc* (gsl-spline-alloc *gsl-interp-cspline* 5))
(defparameter *xarray* (foreign-alloc :double :initial-contents '(1d0 2d0 3d0 4d0 5d0))) (defparameter *yarray* (foreign-alloc :double :initial-contents '(1d1 2d1 3d1 4d1 5d1)))
(gsl-spline-init *gsl-spline-alloc* *xarray* *yarray* 5) (format t "~A~%" (gsl-spline-eval *gsl-spline-alloc* 3.4d0 *gsl-int-acc-alloc*))
(foreign-free *xarray*) (foreign-free *yarray*)
(gsl-spline-free *gsl-spline-alloc*) (gsl-interp-accel-free *gsl-int-acc-alloc*)
Heiko