[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
As the document correctly points out, calls from Scheme to C can be a lot
more efficient, if it is known that callbacks into Scheme do not occur.
This applies to Chicken (for example), where all sorts of weird things
happen in such a case. So, here I'm down on my knees, *begging* for
forms of Scheme->C calls that forbid callbacks. This also simplifies the
case when threads are involved (if thread-switches can only occur in Scheme
code). Note that Scheme->C calls outnumber Scheme->C->Scheme ones usually
a large amount.
It's absolutely unnecessary to specify which C-level forms are macros,
or which are functions. Leave that to the implementors, and allow all
the forms to be macros instead. Whether SCHEME_EXPORT_FUNCTION expands
into "scheme_define_exported_binding" or into something different is
unimportant. Moreover, it might be helpful to change the references
of "scheme_define_exported_binding" and "scheme_enter_pointer" to
since obviously the macro-versions are meant here. Look how the (case-
distinction between functions and macros already produced some confusion!
Defining bindings from C is allowed, and the SRFI-document specifically
points out the C init-code may run before Scheme init-code. Yet,
SCHEME_DEFINE_EXPORTED_BINDING may GC, even before Scheme init-code has
Weird. Or does "Scheme initialization code" not include the basic setup of
the Scheme system - if not, please state so explicitly.
I find it a bit tricky to exactly specify what may GC and what not.
For example: mutations (a la "SCHEME_RECORD_SET") may very well allocate
storage (if the write-barrier involves allocating something on the heap,
that describes the mutated slot). The life-time of data on the heap
may be extremely short - what happens if GC or finalizers run in a
The authors would do good by not assuming every Scheme implementation does
it like S48 or PLT.
Alternative approaches would be:
1) Selectively switch GC on/off in sections of C code (just like critical
2) Allocate *once* a complete chunk that will be able to hold all
data needed subsequently without triggering a GC.
Numeric types: complex numbers are not required by R5RS. I would propose
making accessors and constructors for extended number types optional.
SCHEME_CALL: "For example, suppose Scheme procedure s0 captures
continuation a and then calls C procedure c0, which in turn calls Scheme
procedure s1. Procedure s1 can safely call the continuation a, because that
is a downward use. When a is called Scheme will remove the portion of the C
stack used by the call to c0."
How do you know that? Why do you specify this? Does this mean a is a
kind of continuation, one that uses longjmp()? What if continuations are
(in a CPS manner)?
"On the other hand, if s1 captures a continuation, that continuation
cannot be used from s0, because by the time control returns to s0 the C
stack used by c0 will no longer be valid. An attempt to invoke an upward
continuation that is closed over a portion of the C stack will raise an
Why should it raise an exception? We are interfacing Scheme with C, so
speed is the matter. Since C is an unsafe language, I propose to remove all
superfluous safety-checks. If I want to write safe code, I use Scheme.
The lack of specification about how exactly foreign code is brought into
the Scheme system is understandable but unfortunate. Although this might
be material for a future SRFI, I would recommend to put a little bit more
thought into this.
I consider an FFI SRFI like this one extremely important, since it may well
be the first step towards a platform-and implementation-independent library
of useful code for Scheme, so I acknowledge the effort put into SRFI-50 by
the authors. Unfortunately it appears to me that this is just a polished
up version of the S48 FFI, dragging in a lot of unnecessary (and
dependent) details which may or may not fit other implementations.
Why have countless macros that access and create Scheme data? Some basic
for defining code callable from Scheme (and vice versa) would be more than
enough, together with a simple system of specifying Scheme->C->Scheme type
mappings. This would also remove the GC-related problems (mostly).
There are many different strategies of implementing a Scheme memory-
and execution model, so it would be much more worthwhile (and in the end
more efficient) to provide a simplified method of simply running chunks of
Scheme data -> C code -> Result value(s). That's it.
Wait, it could be made even more interesting: specify a mapping of Scheme
types to abstract foreign types, then add type-mappings for different
languages (C, Java, etc.),
and a simple interface for invoking blocks of foreign code and returning