📄 ch26.htm
字号:
12 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Look at lines 34 and 35 in Listing 26.9. The returned values from
the Perl function are picked off one at a time using the <TT><FONT FACE="Courier">POPn</FONT></TT>
macro to get double values from the stack. The global stack is
readjusted before returning from the C function.
<HR>
<BLOCKQUOTE>
<B>Listing 26.9. Calling the </B><TT><B><FONT FACE="Courier">GetRatio</FONT></B></TT><B>
function.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 /* How
to return lists back from Perl functions */<BR>
2<BR>
3 #include <stdio.h><BR>
4 #include <EXTERN.h><BR>
5 #include <perl.h><BR>
6<BR>
7 static void getRatio(int
a, int b);<BR>
8 static PerlInterpreter *my_perl;
<BR>
9<BR>
10 int main(int argc, char **argv,
char **env)<BR>
11 {<BR>
12 my_perl
= perl_alloc();<BR>
13 perl_construct(my_perl);
<BR>
14 perl_parse(my_perl,
NULL, argc, argv, env);<BR>
15 getRatio(8,3);<BR>
16 perl_destruct(my_perl);
<BR>
17 perl_free(my_perl);
<BR>
18 }<BR>
19<BR>
20<BR>
21 static void getRatio(int a, int
b)<BR>
22 {<BR>
23 dSP ;
<BR>
24 int count
;<BR>
25 ENTER
;<BR>
26 SAVETMPS;
<BR>
27 PUSHMARK(sp)
;<BR>
28 XPUSHs(sv_2mortal(newSViv(a)));
<BR>
29 XPUSHs(sv_2mortal(newSViv(b)));
<BR>
30 PUTBACK
;<BR>
31 count
= perl_call_pv("GetRatio", G_ARRAY);<BR>
32 SPAGAIN
;<BR>
33 if (count
!= 2) croak("Whoa! \n") ;<BR>
34 printf
("%d / %d = %f\n", a, b, POPn) ;<BR>
35 printf
("%d / %d = %f\n", b, a, POPn) ;<BR>
36 PUTBACK
;<BR>
37 FREETMPS
;<BR>
38 LEAVE
;<BR>
39 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Placing <TT><FONT FACE="Courier">G_SCALAR</FONT></TT> instead
of <TT><FONT FACE="Courier">G_ARRAY</FONT></TT> in the code in
Listing 29.9 would have forced a scalar value to be returned.
Only the last item of the array would have been returned and the
value of <TT><FONT FACE="Courier">count</FONT></TT> would be set
to <TT><FONT FACE="Courier">1</FONT></TT>.
<P>
Note how this Perl subroutine takes precautions not to crash by
first checking the divisor by zero. Now, this time let's not return
a value. Instead, let's call the <TT><FONT FACE="Courier">die()</FONT></TT>
function if a bogus value is sent into the function <TT><FONT FACE="Courier">GetRatio</FONT></TT>.
We'll try to trap the errors caused by calling the function with
the <TT><FONT FACE="Courier">G_EVAL</FONT></TT> flag set.
<H2><A NAME="UsingG_EVAL"><B><FONT SIZE=5 COLOR=#FF0000>Using
</FONT></B><TT><B><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">G_EVAL</FONT></B></TT></A>
</H2>
<P>
The <TT><FONT FACE="Courier">G_EVAL</FONT></TT> flag is useful
when calling functions you think may <TT><FONT FACE="Courier">die()</FONT></TT>.
The <TT><FONT FACE="Courier">G_EVAL</FONT></TT> flag is <TT><FONT FACE="Courier">OR</FONT></TT>-ed
in with any other flags to such a call. Listing 26.10 presents
a Perl function that calls the <TT><FONT FACE="Courier">die</FONT></TT>
function in case one of the arguments sent into it is zero. Because
we know that this function can <TT><FONT FACE="Courier">die</FONT></TT>,
we'll send in a value that causes it to <TT><FONT FACE="Courier">die</FONT></TT>.
The code to make this fatal call (to illustrate how <TT><FONT FACE="Courier">G_EVAL</FONT></TT>
is used) is shown in Listing 26.11.
<HR>
<BLOCKQUOTE>
<B>Listing 26.10. A Perl function that can </B><TT><B><FONT FACE="Courier">die</FONT></B></TT><B>.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 sub GetRatioEval<BR>
2 {<BR>
3 my($a,
$b) = @_ ;<BR>
4 my $c, $d;<BR>
5 die "Hey! A is 0 \n"
if ($a == 0);<BR>
6 die "Hey! B is 0 \n"
if ($b == 0);<BR>
7 $c = $a/$b;<BR>
8 $d = $b/$a;<BR>
9 ($c,$d);
<BR>
10 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<HR>
<BLOCKQUOTE>
<B>Listing 26.11. A C program to use the </B><TT><B><FONT FACE="Courier">G_EVAL</FONT></B></TT><B>
flag.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 /* Call the suicidal
function to use G_EVAL */<BR>
2<BR>
3 #include <stdio.h><BR>
4 #include <EXTERN.h><BR>
5 #include <perl.h><BR>
6<BR>
7 static void getRatio(int
a, int b);<BR>
8 static PerlInterpreter *my_perl;
<BR>
9<BR>
10 int main(int argc, char **argv,
char **env)<BR>
11 {<BR>
12 my_perl
= perl_alloc();<BR>
13 perl_construct(my_perl);
<BR>
14 perl_parse(my_perl,
NULL, argc, argv, env);<BR>
15 getRatio(8,0);
<BR>
16 perl_destruct(my_perl);
<BR>
17 perl_free(my_perl);
<BR>
18 }<BR>
19<BR>
20<BR>
21 static void getRatio(int a, int
b)<BR>
22 {<BR>
23 dSP ;
<BR>
24 int count
;<BR>
25 SV
*svp; /*
New line */<BR>
26 ENTER
;<BR>
27 SAVETMPS;
<BR>
28 PUSHMARK(sp)
;<BR>
29 XPUSHs(sv_2mortal(newSViv(a)));
<BR>
30 XPUSHs(sv_2mortal(newSViv(b)));
<BR>
31 PUTBACK
;<BR>
32 count
= perl_call_pv("GetRatioEval", G_ARRAY | G_EVAL);<BR>
33 SPAGAIN
;<BR>
34 svp =
GvSV(gv_fetchpv("@", TRUE, SVt_PV));<BR>
35 if (SvTRUE(svp))
<BR>
36 {<BR>
37 printf
("Die by division: %s\n", SvPV(svp, na)) ;<BR>
38 POPs
;<BR>
39 }<BR>
40 else<BR>
41 {<BR>
42 if (count
!= 2) croak("Whoa! \n") ;<BR>
43 printf
("%d / %d = %f\n", a, b, POPn) ;<BR>
44 printf
("%d / %d = %f\n", b, a, POPn) ;<BR>
45 }<BR>
46 PUTBACK
;<BR>
47 FREETMPS
;<BR>
48 LEAVE
;<BR>
49 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
In the code shown in Listing 26.11, the call to the Perl function
will terminate in a <TT><FONT FACE="Courier">die()</FONT></TT>
function call. The returned value from this Perl function call
is checked in line 34. The variable we are looking at is the <TT><FONT FACE="Courier">$@</FONT></TT>
variable in Perl. The syntax for this call is
<BLOCKQUOTE>
<TT><FONT FACE="Courier">svp = GvSV(gv_fetchpv("@",
TRUE, SVt_PV));</FONT></TT>
</BLOCKQUOTE>
<P>
The value of the variable is checked in the following lines, and
the stack is adjusted with a call to pop off the string. The string
is retrieved with a call to the <TT><FONT FACE="Courier">SvPV()</FONT></TT>
function in line 38.
<H2><A NAME="GettingSpecialVariableValues"><B><FONT SIZE=5 COLOR=#FF0000>Getting
Special Variable Values</FONT></B></A></H2>
<P>
In Listing 26.7 we recovered values of special variables, <TT><FONT FACE="Courier">$<</FONT></TT>
and <TT><FONT FACE="Courier">$(</FONT></TT>, to get the UID and
GID of the calling process via a Perl subroutine. The Perl subroutine
was simply an example of how to call a routine. Now let's see
how we can get values of special variables in Perl directly. The
call to get these values is
<BLOCKQUOTE>
<TT><FONT FACE="Courier">svp = GvSV(gv_fetchpv(variableName, defaultValue,
SVt_PV));</FONT></TT>
</BLOCKQUOTE>
<P>
Let's look at the function in Listing 26.12 to see how to get
the UID and GID of a calling C program.
<HR>
<BLOCKQUOTE>
<B>Listing 26.12. Function for getting the values of </B><TT><B><FONT FACE="Courier">$<</FONT></B></TT><B>
and </B><TT><B><FONT FACE="Courier">$(</FONT></B></TT><B> directly.
<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 static int getUserInfo()<BR>
2 {<BR>
3 dSP ;<BR>
4 int tmp;<BR>
5 SV *svp;<BR>
6 PUSHMARK(sp);<BR>
7 svp = GvSV(gv_fetchpv("<",
0, SVt_PV));<BR>
8 tmp = SvIV(svp);<BR>
9 printf ("\n UID = %d"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -