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
> [email protected]
> https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer
>
_______________________________________________
Gimp-developer mailing list
[email protected]
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer