Georges KO <gko@gko.net> wrote:
+---------------
| "Adam Duston, 773.702.6289" <adam@crsp.uchicago.edu> writes:
| > ...installed DrScheme and it is a wonderful program.
|
| Does it do foreign functions?
+---------------
No, and yes... and yes (sort of).
1. No, there isn't the kind of formal run-time FFI you find in some
other versions of Scheme, in the sense of something that lets you
transparently & automatically coerce Scheme types back & forth into
C or C++ native types, given a simple C-like declaration in Scheme.
2. Yes, there is a [separate] package called "xctocc" that (given such
declarations) generates glue code to allow MzScheme (the Scheme
implementation underneath the DrScheme environment) to call and
be called by C++ classes (used, for example, to glue MrEd & DrScheme
to the C++ based wxWindows GUI system). See:
http://www.cs.rice.edu/CS/PLT/packages/doc/xctocc/index.htm
3. Yes, it's really quite easy (as it is also in SCM, Guile, SIOD, and most
other Schemes) to write dynamically-loadable extensions (new primitives)
for MzScheme in C. It's copiously documented how to do this in:
http://www.cs.rice.edu/CS/PLT/packages/doc/insidemz/index.htm
The only "problem" (if indeed it's a problem for you) is that the
C code has to deal with native Scheme types (since in essence it
becomes an extension of the interpreter). But in MzScheme there are
lots of handy interface routines available to do the conversions
(amply documented in the above URL). To pass integers, doubles,
strings, and chars back & forth is practically trivial. (More complex
types are, well, more complex. ;-} )
For example, suppose MzScheme didn't have an "exit" call [it does],
and you wanted to add one, but you wanted it to be in a shared lib
(because not *all* of your Scheme programs needed to exit, maybe).
Here's the *total* of what it takes (and most of it's type- and
error-checking code):
#include <stdlib.h>
#include "/usr/local/lib/plt/collects/mzscheme/include/escheme.h"
Scheme_Object *my_exit(int argc, Scheme_Object *argv[])
{ long exit_value = 0;
if (arg == 0)
exit(0); /* with no args, just exit cleanly */
else if (!SCHEME_NUMBERP(argv[0]))
scheme_wrong_type("exit", "integer", 0, argc, argv);
else if (!scheme_get_int_val(argv[0], &exit_value))
scheme_signal_error("exit: couldn't convert arg to int");
else
exit((int)exit_value);
/*NOTREACHED*/
return scheme_void;
}
Scheme_Object *scheme_reload(Scheme_Env *env) {return scheme_void;}
/* called the first time (load-extension "thisfile.so") is done.
* Note that we specify "exit" to accept from 0 to 1 argument.
*/
Scheme_Object *scheme_initialize(Scheme_Env *env)
scheme_add_global("exit",
scheme_make_prim_w_arity(my_exit, "exit", 0, 1),
env);
/* In a bigger library, more
* initialization would go here ...
*/
return scheme_void;
}
Compile & link it (following the directions in the URL), producing
(say) "my_lib.so". At run-time, in your Scheme program say:
(load-extension "my_lib.so")
and then when you're ready to give (say) an error exit:
(display "usage: my_prog args...")
(newline)
(exit 1)
-Rob
-----
Rob Warnock, 7L-551 rpw3@sgi.com http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
2011 N. Shoreline Blvd. FAX: 650-933-4392
Mountain View, CA 94043 PP-ASEL-IA