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 <glimmer07@xxxxxxxxx>: > 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@xxxxxxxxxxxxxxxxxxxxxx > https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer > _______________________________________________ Gimp-developer mailing list Gimp-developer@xxxxxxxxxxxxxxxxxxxxxx https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer