| 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