[gambit-list] calling interpreted scheme code from compiled C code
Marc Feeley
feeley at iro.umontreal.ca
Tue Jan 20 10:33:31 EST 2009
On 19-Jan-09, at 8:57 PM, Frederick LeMaster wrote:
> You could define a 'hook' the way emacs and guile do.
>
> ;wrapper.scm
> (define disp-hook (list (lambda () (void))))
>
> (define (add-hook hook thunk)
> (set-cdr! hook (cons thunk '())))
>
> (define (run-hook hook)
> (for-each (lambda (p) (p)) hook))
>
> (c-define (c-disp) () void "f" "" (run-hook disp-hook))
>
> ;test.scm
> (load "graphics")
>
> (define (disp)
> (glClear GL_COLOR_BUFFER_BIT)
> (glutWireTeapot 0.5))
>
> (add-hook disp-hook disp)
>
Nice solution! Another approach, which preserves the GLUT API, is to
replace
(define glutDisplayFunc
(c-lambda ((function () void)) void "glutDisplayFunc"))
with
(define (glutDisplayFunc func)
(real-glutDisplayFunc (scheme-void-function->c-void-function func)))
(define real-glutDisplayFunc
(c-lambda ((function () void)) void "glutDisplayFunc"))
(define (scheme-void-function->c-void-function func)
(set! scheme-void-function func)
c-void-function)
(c-define (c-void-function) () void "c_void_function" ""
(scheme-void-function))
(define scheme-void-function #f)
Note that with this approach only one callback can be installed but
that's OK because GLUT has a single display callback.
In a more general context you could use the following scheme-void-
function->c-void-function procedure definition which allocates C
functions from a pool of 5 predefined functions (basically a poor
implementation of C closures):
(c-define (f0) () void "f0" "" (f 0))
(c-define (f1) () void "f1" "" (f 1))
(c-define (f2) () void "f2" "" (f 2))
(c-define (f3) () void "f3" "" (f 3))
(c-define (f4) () void "f4" "" (f 4))
(define c-void-functions (vector f0 f1 f2 f3 f4))
(define scheme-void-functions (vector #f #f #f #f #f))
(define (f i) ((vector-ref scheme-void-functions i)))
(define (scheme-void-function->c-void-function func)
(let loop ((i 0))
(if (< i (vector-length scheme-void-functions))
(if (vector-ref scheme-void-functions i)
(loop (+ i 1))
(begin
(vector-set! scheme-void-functions i func)
(vector-ref c-void-functions i)))
(error "can't convert Scheme function to C function" func))))
The limit of 5 could of course be increased, but some limit will exist
unless you are willing to accept a non-portable solution.
Gambit's C-interface actually includes code to convert any Scheme
function to a C function by using the technique of dynamic code
generation. This feature is disabled by default because it is a non-
portable solution (it supports x86, SPARC and PowerPC) and it hasn't
been tested thoroughly (check ___make_c_closure in lib/os_dyn.c for
details). If you want to try it out you'll have to build Gambit from
scratch using this (rather cryptic) invocation of the configure script:
CC="gcc -D___WORD_SIZE=___WORD_WIDTH" ./configure
If you do try it out, please let me know how it works out.
Marc
More information about the Gambit-list
mailing list