Subject: Re: Mixing Scheme and C [was: Which Scheme are you using?]
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 1998/06/09
Newsgroups: comp.lang.scheme
Message-ID: <6li8j1$2eqj@fido.engr.sgi.com>

Marius Vollmer  <mvo@zagadka.ping.de> wrote:
+---------------
| > But *nothing* can protect you against inherently broken semantics in
| > the foreign code -- you can't *NOT* "allow these `C-ish' semantics
| > to creep into Scheme interfaces" if you insist on using external C code.
| 
| With "C-ish semantics" I was referring to the rules one has to follow
| when using C code, even bug-free C code.  "printf" is actually a good
| example.  The C semantics are...
+---------------

No. Those are *NOT* "C" semantics, they're *printf* semantics. That is,
a properly constructed ANSI header file for "printf" does *NOT* tell you
anything about the *semantics* of the format string, only that it's a string,
and that "varargs" are being used.

+---------------
| > `printf("%s");' crashes (or equiv.) when you do it in a C program -- how
| > could you possibly expect it *not* to crash when you call it [the *same*
| > underlying library routine] from a Scheme program?
| 
| I would expect to get an error message like
|   > (printf "%s")
|   ERROR: wrong number of agruments.
+---------------

That's because *you* know the unwritten [that is, unwritten in the C prototype]
semantic rules for "printf". But how is a generic FFI generator going to know,
if all it has to work with is the ANSI C prototypes of the functions??!?

And before we carry the "printf" red herring any further and note that ANSI C
*has* [I think] defined what legal format strings to "printf" look like, let's
forget the standard "printf" entirely. Suppose instead we're dealing with a
C function that accepts exactly two arguments:

	void my_msg(int code, int **params);

and the behavior of this is that depending on the value of "code", it will
choose some internal string and none or some of the "params" pointers and
will use them in some way, e.g., pss them to "printf" as arguments. Now
depending on the *internal* behavior of "my_msg" (which we don't get to see,
remember, since it's hidden in some shared lib we're just linking to), suppose
it happens to be the case that the following calls all produce fine & dandy
results:

	int x=3, y=4, *z[] = {&x, &y, NULL};

	my_msg(37, z);
	my_msg(53, NULL);
	my_msg(14, &z[1]);

but these calls all cause core dumps:

	my_msg(17, NULL);
	my_msg(73, z);

How are you going to protect against *that* with your Scheme wrapper
without re-implementing "my_msg" completely from scratch in Scheme
(which you can't do since you can't get at the source)??!?


-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