Hi,
I have committed a rather simple implementation of callbacks for ECL,
with a syntax resembling that of CFFI.
Unfortunately, and in contrast to ECL's SI::CALL-CFUN this
implementation does rely on the compiler. I thought about trying
something different but that would be far too difficult, as it would
involve dynamically creating assembly code, plus allocating regions of
executable memory, etc, etc.
Both the implementation of callbacks and of dynamically generated calls
to C functions (SI::CALL-CFUN) are experimental code. Critics and
suggestions are welcome.
Enjoy,
Juanjo
An example file: foo.lsp
(ffi:defcallback foo :int ((a :int))
(1+ a)
)
(dotimes (i 10)
(print (list i (si::call-cfun (ffi:callback 'foo) :int '(:int) (list
i)))))
Resulting session:
~/src/ecls-new/build$ ecl
ECL (Embeddable Common-Lisp) 0.9g
Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
Copyright (C) 1993 Giuseppe Attardi
Copyright (C) 2000 Juan J. Garcia-Ripoll
ECL is free software, and you are welcome to redistribute it
under certain conditions; see file 'Copyright' for details.
Type :h for Help. Top level.
> (compile-file "foo")
;;; Loading #P"/home/jlr/lib/ecl/cmp.fas"
;;; Loading #P"/home/jlr/lib/ecl/sysfun.lsp"
;;; Compiling foo.
;;; End of Pass 1.
;;; Emitting code for FOO.
;;; Note: Emiting FUNCALL for FFI:CALLBACK
;;; Calling the C compiler...
;;; Note:
;;; Invoking external command: gcc -I../include -g -O2 -fPIC
-fstrict-aliasing -Dlinux -O "-I/home/jlr/lib/ecl//h" -w -c "foo.c" -o
"foo.o"
;;; Note:
;;; Invoking external command: gcc -o "foo.fas" -L"/home/jlr/lib/ecl/"
"foo.o" -Wl,--rpath,/home/jlr/lib/ecl/ -shared -lecl -ldl -lm
-lgmp
;;; OPTIMIZE levels: Safety=2, Space=0, Speed=3
;;; Finished compiling foo.
#P"/home/jlr/src/ecls-new/build/foo.fas"
NIL
NIL
> (load "foo")
;;; Loading #P"foo.fas"
(0 1)
(1 2)
(2 3)
(3 4)
(4 5)
(5 6)
(6 7)
(7 8)
(8 9)
(9 10)
#P"foo.fas"