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"