Ilya Zakharevich on Fri, 21 Nov 1997 06:20:13 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: Math::Pari 0.91 released |
Karim Belabas writes: > > > (a technical question by the way, since I don't have the time to check it > > > myself now: do you still rely on the 'x' code in identifier and the foreign* > > > autoloading mechanism ? > > > > Sure. Though I found a big deficiency: the actual number of args is not > > reported to the foreigh function. If somebody else uses 'x' [...] > > I don't think anybody else uses it. PariPython does not, neither does CLISP, > and neither do we. So feel free to send a patch. Could you post an example of > foreignHandler so that I see how you use it precisely ? (and maybe we could > document the whole mechanism after all this time...). Saving you a peak into Pari.xs, pariErr = &perlErr; foreignHandler = (void*)&callPerlFunction; foreignAutoload = &autoloadPerlFunction; foreignExprSwitch = (char)SVt_PVCV; foreignExprHandler = &exprHandler_Perl; foreignFuncFree = &freePerlFunction; GEN callPerlFunction(entree *ep, ...) { va_list args; char *s = ep->code; int numargs = ep->code[-1]; SV *cv = (SV*) ep->value; GEN res; int i; dSP; int count ; long oldavma = avma; SV *oPariStack = PariStack; SV *sv; va_start(args, ep); ENTER ; SAVETMPS; SAVEINT(sentinel); sentinel = avma; PUSHMARK(sp); EXTEND(sp, numargs + 1); for (i = 0; i < numargs; i++) { PUSHs(pari2mortalsv(va_arg(args, GEN), oldavma)); } va_end(args); PUTBACK; count = perl_call_sv(cv, G_SCALAR); SPAGAIN; if (count != 1) croak("Perl function exported into PARI did not return a value"); sv = SvREFCNT_inc(POPs); /* Preserve the guy. */ PUTBACK ; FREETMPS ; LEAVE ; /* Now PARI data created inside this subroutine sits above oldavma, but the caller is going to unwind the stack: */ if (PariStack != oPariStack) moveoffstack_newer_than(oPariStack); /* Now, when everything is moved off stack, and avma is reset, we can get the answer: */ res = sv2pari(sv); /* XXXX When to decrement the count? */ /* We need to copy it back to stack, otherwise we cannot decrement the count. XXXX not necessary! */ avma -= taille(res)<<TWOPOTBYTES_IN_LONG; brutcopy(res, avma); SvREFCNT_dec(sv); return (GEN)avma; } /* Currently with <=6 arguments only! */ long autoloadPerlFunction(char *s, long len) { CV *cv; SV* name = sv_2mortal(newSVpv(s, len)); cv = perl_get_cv(SvPVX(name), FALSE); if (cv == Nullcv) { return 0; } /* Got it! */ installPerlFunction((SV*)cv, SvPVX(name), -1, NULL); /* -1 gives variable. */ return 1; } GEN exprHandler_Perl(char *s) { SV* dummy; SV* cv = (SV*)(s - LSB_in_U32 - ((char*)&(dummy->sv_flags) - ((char*)dummy))); GEN res; long count; dSP; SV *sv; SV *oPariStack = PariStack; ENTER ; SAVETMPS; PUSHMARK(sp); SAVEINT(sentinel); sentinel = avma; count = perl_call_sv(cv, G_SCALAR); SPAGAIN; sv = SvREFCNT_inc(POPs); /* Preserve it through FREETMPS */ PUTBACK ; FREETMPS ; LEAVE ; /* Now PARI data created inside this subroutine sits above oldavma, but the caller is going to unwind the stack: */ if (PariStack != oPariStack) moveoffstack_newer_than(oPariStack); /* Now, when everything is moved off stack, and avma is reset, we can get the answer: */ res = sv2pari(sv); /* We need to copy it back to stack, otherwise we cannot decrement the count. */ avma -= taille(res)<<TWOPOTBYTES_IN_LONG; brutcopy(res, avma); SvREFCNT_dec(sv); return (GEN)avma; } > If you wish (although the Configure checks for a libgnuplo.a which of course > it never finds...). I had a casual look at this plotgnuplot.c long ago (had > many many other pressing things to do at the time...), and it seemed to me it > needed to be linked with some other library hacked from the GNU package, > right ? And this is definitely not included yet. If I can figure out how it > works, I'll try to include it in one of the next alpha updates. Well, if you use the newer variant from 0.91, you do not need to link with anything. ;-) ;-) Really. You can load gnuplot at runtime (but the DLL should be compiled nevertheless, of course - with enough hacking power to call a correct fixup function one can probably even use Perl's Term::Gnuplot DLL without any recompile). Makemakefile of pari-small.zip contained all the necessary logic: you need to have the directory with the source of gnuplot3.5 handy, you need to compile 3 or 4 files from this distribution, and link against them. Ilya