Hi There,
Given the following (latest svn today - parrot 0.49+):
.namespace ['Foo']
.sub invoke :vtable
say "you invoked me!"
.return()
.end
.sub main :main
$P0 = newclass "Foo"
$P1 = new "Foo"
$P1()
say "got here"
.end
The final "got here" is never printed.
Also parrot segfaults with the signature:
.sub invoke :vtable :method
...
.end
Not sure if that's allowed (:vtable :method), though.
Cheers,
Rich
Any ParrotObject overriding the invoke vtable method is probably not
going to care about addresses. Luckily, all we have to do is return
the address we're given, so everything goes back to normal after the
method's finished. The downside is that you're going to have to come
with a more creative workaround in order to be passed any arguments
that the method is called with.
.namespace ['Foo']
.sub __invoke :method
.param int address
say "you invoked me!"
.return(address)
.end
.sub main :main
$P0 = newclass "Foo"
$P1 = new "Foo"
$P1()
say "got here"
.end
Thanks,
Alek Storm
On 3/7/07, via RT richard @ hive-systems. com
I don't think that's the right route to take. Exposing the pc to PIR-land
code seems dangerous and I don't think there's much point. As a PIR user, I
want the invoke vtable to behave just like any other PIR subroutine.
This gets us close to what I want:
void* invoke(void *next) {
STRING *meth = CONST_STRING(interp, "__invoke");
STRING *meth_v = CONST_STRING(interp, "invoke");
PMC *sub = Parrot_find_vtable_meth(interp, pmc, meth_v);
if (PMC_IS_NULL(sub))
sub = find_or_die(interp, pmc, meth);
(void*) Parrot_run_meth_fromc_args(interp, sub,
pmc, meth, "??", next);
return next;
}
I've tested it and it works with the original code that Richard gave. The
only thing left to do is handle return values; I'm still working on that. If
I can get return values working properly, I'll check in a fix.
--
Matt Diephouse
http://matt.diephouse.com
> I don't think that's the right route to take. Exposing the pc to PIR-land
> code seems dangerous and I don't think there's much point. As a PIR user, I
> want the invoke vtable to behave just like any other PIR subroutine.
Agreed.
> This gets us close to what I want:
>
>
>
> void* invoke(void *next) {
>
> STRING *meth = CONST_STRING(interp, "__invoke");
>
> STRING *meth_v = CONST_STRING(interp, "invoke");
>
> PMC *sub = Parrot_find_vtable_meth(interp, pmc, meth_v);
>
> if (PMC_IS_NULL(sub))
>
> sub = find_or_die(interp, pmc, meth);
>
> (void*) Parrot_run_meth_fromc_args(interp, sub,
>
> pmc, meth, "??", next);
That probably works, with the caveat that the Parrot_run_*_fromc*() functions
seem to have big problems with multisubs.
-- c
We all missed the obvious solution: just invoking the sub, rather than entering a new
runloop. This has the benefits of not creating a new runloop and of handling parameters and
return values properly. It may even make invoke work with :multi (it might need a bit more
work for that).
Fixed in r17385.
--
Matt Diephouse
void* invoke(void *next) {
STRING *meth = CONST_STRING(interp, "__invoke");
STRING *meth_v = CONST_STRING(interp, "invoke");
PMC *sub = Parrot_find_vtable_meth(interp, pmc, meth_v);
if (PMC_IS_NULL(sub))
sub = find_or_die(interp, pmc, meth);
INTERP->current_object = SELF;
return VTABLE_invoke(interp, sub, next);
}