[plt-scheme] Linking Scheme- and C-variables

From: Richard Cleis (rcleis at mac.com)
Date: Sat Nov 1 15:06:40 EST 2003

On Saturday, November 1, 2003, at 11:57 AM, Daniel K. Skovenborg wrote:

>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>> I access c-doubles, for example, by making a
>> closure-like primitive for
>> each variable:
>> scheme_add_global( "access-the-double",
>> 		       scheme_make_closed_prim_w_arity(
>> AccessADouble,
>> &theDouble,
>> "access-the-double",
>> 0, 1), e);
>> AccessADouble is written to return theDouble with
>> scheme_make_double(theDouble).  If a parameter is
>> supplied, it is
>> validated then stored in theDouble first.
>> Ie, (access-the-double 12.3) "sets" theDouble to
>> 12.3.
>> (access-the-double) "gets" 12.3 .
> That's exactly what I'm trying to avoid: making access-functions for
> each variable that should be used :)

AccessADouble is only written once, and can be bound to as many 
variables as you care to register with scheme_make_closed_prim_w_arity.

To handle groups of values, I have also written primitives that map 
scheme lists to c-arrays.  Mapping lists to C++ properties might be 
more suitable for your purpose.

> But now that access-functions is the only way to do it, what do people
> here thinks of the following solutions I thought of (please note that
> it's a game I'm making, so be performance-minded):
> 1. The variables are stored in C, so to speak, and all variables are
>    registered in a std::map <std::string, T*> (yes, I use C++. Please
>    don't kill me ;)) where T* is a pointer to the type (so there's one
>    map for each type used).
>    We can now make an access-function for each type instead of each
>    variable.

That's what the closure primitive provides.  And you can "do-tricks" by 
passing a structure pointer to the primitive.  Members of the structure 
can contain instructions for the primitive, even if the primitive only 
returns a value from the structure.

>    So to access the integer foo we use
>     (get-int "foo")
>    which will look for the key "foo" in the map containg pointers to 
> the
>    integers and return the value of the integer pointed to by the item
>    with the key "foo". And similar we can set foo to 42 with
>     (set-int "foo" 42)
>    and the use the hack posted by Eli Barzilay while I was writing
>    this mail.
>    The stupid thing about this method, I guess, is that the map should
>    be managed the whole time (when making/deleting variables).
> 2. The variables are in the Scheme environment and can be accessed in
>    similar ways:
>     SCHEME_INT_VAL( scheme_evaluate_string("foo", env) ) to get the
>    value  of the integer foo. To set the variable:
>     Scheme_Object * args[2] = {scheme_evaluate_string("foo", env),
>                                scheme_make_integer(42)};
>     scheme_apply(set, 2, args);
>    where
>     Scheme_Object * set = scheme_evaluate_string("set!", env);
>    This could either be encapsulated in C-functions (taking a string
>    argument that contains the name of the variable) or in a class (one
>    for each type) with overloaded 'type'-operator (for example operator
>    int for the integer-wrapper class) and = operator. I like the latter
>    best.
> So what do the gurus here think?
>> I veered away from the set! route since I don't like the idea of
>> parallel universes of variables when the two languages are so
>> different.  What happens if a c-double shadows a scheme variable that
>> is set with (sqrt -1) ?
> Mmh, yes, I'll have to watch my step.

Posted on the users mailing list.