tromey / emacs-ffi

FFI for Emacs
99 stars 17 forks source link

How to make a custom type/struct and use it? #15

Closed jkitchin closed 7 years ago

jkitchin commented 7 years ago

I am trying to use the emacs-ffi to work out this example: https://www.gnu.org/software/gsl/manual/html_node/Numerical-integration-examples.html#Numerical-integration-examples

I am stumbling on this:

gsl_function F; F.function = &f; F.params = α

I thought it would look like this:

(define-ffi-struct gsl_function (function :type :pointer) (params :type :pointer))

(let* ((*w (gsl-integration-workspace-alloc 1000))
       (F (ffi--define-struct gsl_function))
       (f (lambda (x params) 2))
       (cif (ffi--prep-cif :double [:pointer :pointer]))
       (*f (ffi-make-closure cif f))
       (a 0.0)
       (b 1.0)
       (epsabs 0.0)
       (epsrel 1e7)
       (limit 1000)
       (result (ffi-allocate :double))
       (abserr (ffi-allocate :double)))
  (setf (gsl_function-function F) *f)
  (gsl-integration-qags F a b epsabs epsrel limit *w result abserr)
  (ffi--mem-ref result :double)) 

The answer should be -4, but it is this instead:

+RESULTS:

: 2.124514105e-314

That seems like maybe I am just reading some nonsense from memory. Is there anything obvious I am doing wrong here?

tromey commented 7 years ago

I didn't try this, but from the link I think this:

       (cif (ffi--prep-cif :double [:pointer :pointer]))

might be wrong, as the f function actually accepts a double as its first argument.

tromey commented 7 years ago

... though I guess that shouldn't matter at all. Sorry about that. No idea offhand, could be a bug, but it would be easier to see with a simpler example.

jkitchin commented 7 years ago

🤦‍♂️ Good call on the wrong cif signature. With that correction, this works fine here. Thanks for looking at it!

#+BEGIN_SRC emacs-lisp :results value

(defun ff (x params) (/ (log x) (sqrt x)))

(let* ((*w (gsl-integration-workspace-alloc 1000))
       (F (ffi--define-struct gsl_function))
       (cif (ffi--prep-cif :double [:double :pointer]))
       (*f (ffi-make-closure cif #'ff))
       (a 0.0)
       (b 1.0)
       (epsabs 0.0)
       (epsrel 1e-7)
       (limit 1000)
       (result (ffi-allocate :double))
       (abserr (ffi-allocate :double)))
  (setf (gsl_function-function F) *f)
  (gsl-integration-qags F a b epsabs epsrel limit *w result abserr)
  (ffi--mem-ref result :double))
#+END_SRC

#+RESULTS:
: -4.000000000000085