I have made some progress with calling Scheme functions from C but do  
not really understand the details and am uncertain if I am doing  
things correctly.


I modified the 'scheme_call()' routine to the following:

   void scheme_call(scheme *sc, pointer func, pointer args) {
      pointer stack = sc->dump; /* save dump_stack position */

      dump_stack_reset(sc);
      sc->envir = sc->global_env;
      sc->args = args;
      sc->code = func;
      sc->interactive_repl =0;
      sc->retcode = 0;
      Eval_Cycle(sc, OP_APPLY);
     sc->dump = stack; /* restore dump_stack position */
     }

This allowed me to define a C foreign function:

   pointer foreign_test_call (scheme * sc, pointer args) {
     pointer func;

     func = sc->vptr->pair_car(args);
     args = sc->vptr->pair_cdr(args);

     scheme_call(sc, func, args);
     return sc->value;
     }

which I could invoke with a command such as:

   => (test-call + 2 3)
   5

or

   => (test-call list 1 2 3)
   (1 2 3)

I don't know if modifying 'scheme_call()' will cause other problems  
(it seems unreferenced elsewhere in TinyScheme, but the authors may  
have other intents); if so, one could provide a separate function  
which does not reset the "dump stack". I don't understand the theory  
or operation of the "dump stack", so maybe there is a better approach  
altogether.


Please understand that this information should be taken with a large  
grain of salt.


Quoting Glimmer Labs <[EMAIL PROTECTED]>:

> 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.
>
> Thanks,
> 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):
> %ld\n",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);
>   fclose(init_scm);
>   scheme_set_output_port_file(sc, stdout);
>   sc->print_flag=1; /* necessary? */
>   sc->print_output=1;
>   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",
> sc->vptr->ivalue(sc->value));
>   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",
> sc->vptr->ivalue(sc->value));
>   printf("defined foreign function twomath, takes two integers and a
> function\n");
>   sc->vptr->scheme_define(
>         sc,
>         sc->global_env,
>         sc->vptr->mk_symbol(sc,"twomath"),
>         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
> call...\n");
>   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
> sc->value\n",sc->vptr->ivalue(sc->value));
>   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
> Gimp-developer@lists.XCF.Berkeley.EDU
> https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer
>



_______________________________________________
Gimp-developer mailing list
Gimp-developer@lists.XCF.Berkeley.EDU
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Reply via email to