Filling the Perl Stack

  • Thread starter Guenther Sohler
  • Start date
G

Guenther Sohler

In my embedded perl I decided to handle a 2D coordinate as
a anonymous reference to an array of 2 numbers like
[ 5.6 , 3.4 ]

Therefore a list of points would be like

[ [ 1,2 ] , [ 3,4 ] , [ 5,6] ]

In C I want to put this onto the perl stack.

I have written this C code.


int j;
AV *points=newAV();
for(j=0;j<pars.points.len();j++)
{
AV *point=newAV();
av_push(point,newSVnv(pars.points[j].x*l.unit_db));
av_push(point,newSVnv(pars.points[j].y*l.unit_db));
av_push(points,newSVrv((SV *) point,NULL));
}
XPUSHs(sv_2mortal(newSVrv((SV *) points,NULL)));


But the data does not arrive in the perl function.
Did I do an error ?
Do I have to use more/less mortal ??
Do I have to free/not free any references, arrays :?

The perl code looks like

sub test
{
$coords=shift;
print scalar(@$coords)." coords found\n";
}

I expect the perl routine to display
"2 coords found"

but it just displays " coords found"

Whats wrong ?
 
T

Tassilo v. Parseval

Also sprach Guenther Sohler:
In my embedded perl I decided to handle a 2D coordinate as
a anonymous reference to an array of 2 numbers like
[ 5.6 , 3.4 ]

Therefore a list of points would be like

[ [ 1,2 ] , [ 3,4 ] , [ 5,6] ]

In C I want to put this onto the perl stack.

I have written this C code.


int j;
AV *points=newAV();
for(j=0;j<pars.points.len();j++)
{
AV *point=newAV();
av_push(point,newSVnv(pars.points[j].x*l.unit_db));
av_push(point,newSVnv(pars.points[j].y*l.unit_db));
av_push(points,newSVrv((SV *) point,NULL));
}
XPUSHs(sv_2mortal(newSVrv((SV *) points,NULL)));


Whitespaces are not a scarce resource, so use them in your code.

Other than that, what is the context codewise of the above snippet?
Evidently it is taken from an XSUB, but how do you return from it? Does
it end on

XSRETURN(1);

?
But the data does not arrive in the perl function.
Did I do an error ?
Do I have to use more/less mortal ??

The mortalizing seems correct. Values in arrays and hashes are
non-mortal, everything returned to the caller should be mortal.
Do I have to free/not free any references, arrays :?

As the above looks correct, that should be taken care of by perl's
garbage-collecting.
The perl code looks like

sub test
{
$coords=shift;
print scalar(@$coords)." coords found\n";
}

That's not too helpful. You haven't shown the part where the XSUB is
called. Also, we don't really know what the XSUB looks like. Relevant
parts of the XSUB would be the declaration and how it processes its
arguments (if any), the population of the array-to-be-returned (which
you showed above) and the actual returning to the caller.

Tassilo
 
G

Guenther Sohler

Dear Tassilo,

thank you for all your answers.

I supposed, that the complete c function calling the perl xsub is not
interesting, because all the rest works. just putting a list
of "coorindates" onto the perl stack does not seem to work.
I dont use the xsubpp compiler. I have everything integrated into my c
program(and it works for everything else)

However I will paste all my function now:



int perl_call(char *func,GsList<PCellParam> &pars)
{
int i,ret;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for(i=0;i<pars.len();i++)
{
switch(pars.type)
{
case PCELL_PAR_NUMBER:
case PCELL_PAR_BOOLEAN:
XPUSHs(sv_2mortal(newSViv(pars.number)));
break;
case PCELL_PAR_METRIC:
XPUSHs(sv_2mortal(newSVnv(pars.metric)));
break;
case PCELL_PAR_STRING:
XPUSHs(sv_2mortal(newSVpv(pars.string.str(),0)));
break;
case PCELL_PAR_CHOICE:
XPUSHs(sv_2mortal(newSVpv(pars.string.str(),0)));
break;
case PCELL_PAR_POINTS:
{
int j;
AV *points=newAV();
for(j=0;j<pars.points.len();j++)
{
AV *point=newAV();
av_push(point,newSVnv(pars.points[j].x*l.unit_db));
av_push(point,newSVnv(pars.points[j].y*l.unit_db));
av_push(points,newSVrv((SV *) point,NULL));
}
XPUSHs(sv_2mortal(newSVrv((SV *) points,NULL)));
}
break;
default: printf("Unsupported Variable type!\n");
exit(1);
break;

}
}
PUTBACK;
ret=call_pv(func,G_SCALAR);
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}

Maybe you see an error ...

Thank you for your help
 
T

Tassilo v. Parseval

Also sprach Guenther Sohler:
I supposed, that the complete c function calling the perl xsub is not
interesting, because all the rest works. just putting a list
of "coorindates" onto the perl stack does not seem to work.
I dont use the xsubpp compiler. I have everything integrated into my c
program(and it works for everything else)

However I will paste all my function now:



int perl_call(char *func,GsList<PCellParam> &pars)
{
int i,ret;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for(i=0;i<pars.len();i++)
{
switch(pars.type)
{
case PCELL_PAR_POINTS:
{
int j;
AV *points=newAV();
for(j=0;j<pars.points.len();j++)
{
AV *point=newAV();
av_push(point,newSVnv(pars.points[j].x*l.unit_db));
av_push(point,newSVnv(pars.points[j].y*l.unit_db));
av_push(points,newSVrv((SV *) point,NULL));
}
XPUSHs(sv_2mortal(newSVrv((SV *) points,NULL)));


Sorry, I am an idiot. I should have seen the error already in your first
posting. For putting a reference to something into the array, you have
to use newRV_(inc|noinc). For your case:

{
...
av_push(points, newRV_noinc((SV*)point));
}
XPUSHs(sv_2mortal(newRV_noinc(SV*)points));

If you read perlapi's entry on newSVrv() a couple of times, you'll
notice that its return value is a new SV that its first argument will
be made a reference to. I can't remember ever having had a use for it
anywhere in my code.

Tassilo
 
G

Guenther Sohler

Hallo Tassilo,

thank you for your answer. It works perfect. You just forgor to put one
pair of paranthesis.
Using perl my program becomes very powerful!
If you want, I can send you a screenshot of a layout generated by perl
code :)
 
T

Tassilo v. Parseval

Also sprach Guenther Sohler:
Hallo Tassilo,

thank you for your answer. It works perfect. You just forgor to put one
pair of paranthesis.
Using perl my program becomes very powerful!
If you want, I can send you a screenshot of a layout generated by perl
code :)

Maybe you can put it into some publicly available spot on the internet
so that everyone here can see it?

Tassilo
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Tassilo v. Parseval
Maybe you can put it into some publicly available spot on the internet
so that everyone here can see it?

At some moment I wanted to just rewrite perlxs so that it is readable,
and use this opportunity to document all the stuff I needed to do in
my XS code... But it was quite some time ago...

Ilya
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,797
Messages
2,569,647
Members
45,380
Latest member
LatonyaEde

Latest Threads

Top