Attempting to map a Scheme function in Script-Fu/Tiny-Fu to an entire
image using the PDB functions gimp-drawable-get-pixel and
gimp-drawable-set-pixel is painfully slow, so we've been trying to
build a mk_foreign_func'ed function to attach to tinyscheme that
updates images in a tile-aware way.

As far as we can tell, the most straightforward methods tinyscheme
provides for Scheme command evaluation from C are a) using the
scheme_load_string function to parse a string of Scheme code, and b)
passing Scheme function and argument pointers to scheme_call.
mk_foreign_func'ed functions receive parameters in the latter format,
so parsing them and building a command string to pass back seems
clunky.  scheme_call, on the other hand, quickly evaluates a closure
passed with arguments and stores the result in sc->value, and we have
had success mapping Scheme functions to large images.

However, mk_foreign_func'ed functions that call scheme_call don't
return correctly, so Scheme code that contains calls to these
functions breaks; we're having trouble figuring out why.  scheme_call
isn't included in scheme.h, so it's probably not even intended for
external use.  We haven't been able to find any documentation for
scheme_call so we don't know whether we're using it correctly or not.

We've been using scheme_call like
scheme_call(<pointer to scheme struct>,
            <pointer to closure>,
            <args list made using cons(sc, pointer arg_1, cons(sc,
arg_2, sc->NIL))>)
Is this the correct way to call scheme_call?  Including this call to
scheme_call in any mk_foreign_func'ed function causes tinyscheme to
fail to process the function's return, i.e., it causes
(func-with-scheme_call foo), (+ 1 (func-with-scheme_call foo) ), etc.
to not evaluate to anything.  When we remove scheme_call calls, our
functions do not have this problem.

We've been trying to learn how Eval_Cycle in scheme.c works to figure
out why this is happening, but it's not going very well.  We're hoping
someone out there knows tinyscheme well enough to tell us what we're
doing wrong.  Below is a program we've been using for testing that
shows how we're calling scheme_call, how calls with/without it behave,
etc.  This won't compile against the GIMP's tinyscheme without adding
a scheme_call prototype to scheme.h, etc.; if you want specifics,
we'll gladly provide them.

We're students, and we've tried to avoid making any egregious errors
in tone/content or etiquette, but if any of this seems weird please
attribute it to our inexperience and tell us why.

Ted Cooper and Emily Jacobson

#include "scheme-private.h"
#include "scheme.h"

pointer twomath(scheme *sc, pointer args);

pointer twomath(scheme *sc, pointer args){
  long result;
  pointer a, b;
  pointer func;
  a = sc->vptr->pair_car(args);
  args = sc->vptr->pair_cdr(args);
  b = sc->vptr->pair_car(args);
  args = sc->vptr->pair_cdr(args);
  func = sc->vptr->pair_car(args);
  printf("  twomath: (pre-scheme_call) sc->vptr->ivalue(sc->value):
  scheme_call(sc, func, cons(sc, a, cons(sc, b, sc->NIL)));
  result = sc->vptr->ivalue(sc->value);
  printf("  twomath: (post-scheme_call) sc->vptr->ivalue(sc->value):
%ld\n", result);
  printf("  twomath: scheme_call sets sc->value to the correct value,
but when we try to return a copy...");
  /*return sc->value;*/
  return sc->vptr->mk_integer(sc,result);


int main(){
  scheme *sc;
  FILE *init_scm;
  sc = scheme_init_new();;
  init_scm = fopen("init.scm","r");
  scheme_load_file(sc, init_scm);
  scheme_set_output_port_file(sc, stdout);
  sc->print_flag=1; /* necessary? */
  printf("regular functions return, produce output, and set sc->value
to some crazy huge number:\n");
  printf(" (pre-scheme_load_string), sc->vptr->ivalue(sc->value):
%ld\n", sc->vptr->ivalue(sc->value));
  printf(" (- 4 4)\n");
  scheme_load_string(sc, "(- 4 4)");
  printf("output above, and (post-scheme_load_string),
sc->vptr->ivalue(sc->value): %ld <- DIFFERENT CRAZY HUGE NUMBER\n",
  printf(" (+ 32 (- 4 5))\n");
  scheme_load_string(sc, "(+ 32 (- 4 5))");
  printf("output above, and (post-scheme_load_string),
sc->vptr->ivalue(sc->value): %ld <- THE SAME CRAZY HUGE NUMBER\n",
  printf("defined foreign function twomath, takes two integers and a
        sc->vptr->mk_foreign_func(sc, twomath));
  printf(" (twomath 1 2 +)\n");
  scheme_load_string(sc, "(twomath 1 2 +)");
  printf("\nit returns no output, and putting it in another function
  printf(" (+ 1 (twomath 1 2 +))\n");
  scheme_load_string(sc, "(+ 1 (twomath 1 2 +))");
  printf("\nstill returns no output, and sc->vptr->ivalue(sc->value):
%ld = the value set in twomath (it hasn't been updated to some crazy
huge number, since + couldn't evaluate without two parameters).  Next,
let's run a command that will evaluate to see what happens to
  printf(" (+ 32 (- 4 5))\n");
  scheme_load_string(sc, "(+ 32 (- 4 5))");
  printf("output above, and (post-scheme_load_string),
sc->vptr->ivalue(sc->value): %ld <- SET BACK TO THE SAME CRAZY HUGE
NUMBER\n", sc->vptr->ivalue(sc->value));

  return 0;

Gimp-developer mailing list

Reply via email to