chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Constructing parameter lists in C: can I use FFI?


From: felix winkelmann
Subject: Re: [Chicken-users] Constructing parameter lists in C: can I use FFI?
Date: Mon, 25 Jul 2005 15:40:30 +0200

On 7/21/05, Daniel B. Faken <address@hidden> wrote:
> 
> Now a preferable solution would be to construct the parameter list,
> as a C_word (scheme-object) via C_list(...), and either
> * use C_callback(scmfn, arglist) for callbacks or
> * use a single entry-point 'scm_applyfn' that takes two
>   scheme-object args and just calls (apply scmfn arglist).

This looks definitely more appropriate. You really want to reduce
the number of switches between Scheme and C (and back).

> The "Problem": its not easy to construct these arglists; or, at least, its
> much harder than using the Chicken-FFI's ability to define & translate
> types (e.g. using define-foreign-type). [an aside: I'm using a
> code-generator, since there are so many functions, but there are about
> 200 different C-function signatures in all]
> 

Since this is performance critical, I'd suggest that you implement the
translation of C to Scheme types yourself (in C). If you are using OpenGL,
the number of argument types you have to support is (relatively) small.
You can (as you correctly suggest), allocate space for the argument lists
on the C-stack. Another method would be to store the arguments in
a Scheme list allocated in static memory (this requires that you store
only immediate or static data in that list), or in a once-allocated list
that is GC-protected (via CHICKEN_new_gc_root()).

Note that mixing callbacks and entry-points can be tricky: an entry-point
leaves a continuation object on the temporary stack. Doing a callback
after an entry-point returned will not work. A better idea might be to
run CHICKEN_run once, with a Scheme toplevel that performs a
##sys#call-host and from then on only invoke Scheme via callbacks:

;;;; x.scm:

(define-external (foo (int x) (c-string y)) double
  (print (list x y)) 
  (sqrt x) )

(##sys#call-host)

/* y.c */

#include "chicken.h"

extern double foo(int, char*);

int main()
{
  CHICKEN_run(NULL, NULL, NULL, C_toplevel);
  C_restore; /* <- pop continuation, unless we call an entry-point
this should be ok, */
  printf("-> %g\n", foo(42, "abc"));
  printf("-> %g\n", foo(32, "abc"));
  return 0;
}

% csc -e x.scm y.c -kv && x
/usr/local/bin/chicken x.scm -output-file x.c -quiet
gcc y.c -o y.o -g -DHAVE_CHICKEN_CONFIG_H -DC_EMBEDDED -c -DC_NO_PIC_NO_DLL
gcc x.c -o x.o -g -DHAVE_CHICKEN_CONFIG_H -DC_EMBEDDED -c -DC_NO_PIC_NO_DLL
gcc -o x y.o x.o -lchicken -L/usr/local/lib -Wl,-R/usr/local/lib -ldl
-lpcre -lffi -lm  -ldl -lpcre -lffi
(42 abc)
-> 6.48074
(32 abc)
-> 5.65685

This is somewhat, well, unorthodox, but might actually work... ;-)


cheers,
felix




reply via email to

[Prev in Thread] Current Thread [Next in Thread]