📄 ch25.htm
字号:
as you scan through the code. Function names in the source code
can begin with <TT><FONT FACE="Courier">sv_</FONT></TT> for scalar
variables and related operations, <TT><FONT FACE="Courier">av_</FONT></TT>
for array variables, and <TT><FONT FACE="Courier">hv_</FONT></TT>
for hashes.
<P>
Let's now cover these variable types and the functions to manipulate
them.
<H2><A NAME="ScalarsandScalarFunctions"><B><FONT SIZE=5 COLOR=#FF0000>Scalars
and Scalar Functions</FONT></B></A></H2>
<P>
Scalar variables in the Perl source are those with <TT><FONT FACE="Courier">SV</FONT></TT>
in their names. A scalar variable on a given system is the size
of a pointer or an integer, whichever is larger. Specific types
of scalars exist to specify numbers such as <TT><FONT FACE="Courier">IV</FONT></TT>
for integer or pointer, <TT><FONT FACE="Courier">NV</FONT></TT>
for doubles, and so on. The <TT><FONT FACE="Courier">SV</FONT></TT>
definition is really a <TT><FONT FACE="Courier">typedef</FONT></TT>
declaration of the <TT><FONT FACE="Courier">sv</FONT></TT> structure
in the header file called <TT><FONT FACE="Courier">sv.h</FONT></TT>.
<TT><FONT FACE="Courier">NV</FONT></TT>, <TT><FONT FACE="Courier">IV</FONT></TT>,
<TT><FONT FACE="Courier">PV</FONT></TT>, <TT><FONT FACE="Courier">I32</FONT></TT>,
and <TT><FONT FACE="Courier">I16</FONT></TT> are type-specific
definitions of <TT><FONT FACE="Courier">SV</FONT></TT> for doubles,
generic pointers, strings, and 32- and 16-bit numbers.
<P>
Floating-point numbers and integers in Perl are stored as doubles.
Thus, a variable with <TT><FONT FACE="Courier">NV</FONT></TT>
will be a double that you can cast in a C program to whatever
type you want.
<P>
Four types of routines exist to create an <TT><FONT FACE="Courier">SV</FONT></TT>
variable. All four return a pointer to a newly created variable.
You call these routines from within an <TT><FONT FACE="Courier">XS</FONT></TT>
Perl extension file:
<UL>
<LI><TT><FONT FACE="Courier">SV *newSViv(IV I);</FONT></TT>
<LI><TT><FONT FACE="Courier">SV *newSVnv(double d);</FONT></TT>
<LI><TT><FONT FACE="Courier">SV *newSVpv(char * p, int len);</FONT></TT>
<LI><TT><FONT FACE="Courier">SV *newSVsv(SV *svp);</FONT></TT>
</UL>
<P>
The way to read these function declarations is as follows. Take
the <TT><FONT FACE="Courier">newSViv(IV)</FONT></TT> declaration,
for example. The <TT><FONT FACE="Courier">new</FONT></TT> portion
of the declaration asks Perl to create a new object. The <TT><FONT FACE="Courier">SV</FONT></TT>
indicates a scalar variable. The <TT><FONT FACE="Courier">iv</FONT></TT>
indicates a specific type to create: <TT><FONT FACE="Courier">iv</FONT></TT>
for integer, <TT><FONT FACE="Courier">nv</FONT></TT> for double,
<TT><FONT FACE="Courier">pv</FONT></TT> for a string of a specified
length, and <TT><FONT FACE="Courier">sv</FONT></TT> for all other
types of scalars.
<P>
Three functions exist to get the value stored in an <TT><FONT FACE="Courier">SV</FONT></TT>.
The type of value returned depends on what type of value was set
at the time of creation:<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=291><TT><FONT FACE="Courier">int SvIV(SV*);</FONT></TT>
</TD><TD WIDTH=299>This function returns an integer value of the <TT><FONT FACE="Courier">SV</FONT></TT> being pointed to. Cast the return value to a pointer if that is how you intend to use it. A sister macro, <TT><FONT
FACE="Courier">SvIVX(SV*)</FONT></TT>, does the same thing as the <TT><FONT FACE="Courier">SvIV</FONT></TT> function.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=291><TT><FONT FACE="Courier">double SvNV(SV*);</FONT></TT>
</TD><TD WIDTH=299>This function returns a floating-point number. The <TT><FONT FACE="Courier">SvNVX</FONT></TT> macro does the same thing as the <TT><FONT FACE="Courier">SvNV()</FONT></TT> function.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=291><TT><FONT FACE="Courier">char *SvPV(SV*, STRLEN len);</FONT></TT>
</TD><TD WIDTH=299>This function returns a pointer to a <TT><FONT FACE="Courier">char</FONT></TT>. The <TT><FONT FACE="Courier">STRLEN</FONT></TT> in this function call is really specifying a pointer to the <TT><FONT FACE="Courier">len</FONT></TT>
variable. The pointer to <TT><FONT FACE="Courier">len</FONT></TT> is used by the function to return the length of the string in <TT><FONT FACE="Courier">SV</FONT></TT>. The <TT><FONT FACE="Courier">SvPVX</FONT></TT> pointer returns the string too, but you
do not have to specify the <TT><FONT FACE="Courier">STRLEN len</FONT></TT> argument.
</TD></TR>
</TABLE></CENTER>
<P>
<P>
You can modify the value contained in an already existing <TT><FONT FACE="Courier">SV</FONT></TT>
by using the following functions:<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=295><TT><FONT FACE="Courier">void sv_setiv(SV* ptr, IV incoming);</FONT></TT>
</TD><TD WIDTH=295>This function sets the value of the <TT><FONT FACE="Courier">SV</FONT></TT> being pointed to by <TT><FONT FACE="Courier">ptr</FONT></TT> to the integer value in <TT><FONT FACE="Courier">incoming</FONT></TT>.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=295><TT><FONT FACE="Courier">void sv_setnv(SV* ptr, double);</FONT></TT>
</TD><TD WIDTH=295>This function sets the value of the <TT><FONT FACE="Courier">SV</FONT></TT> being pointed to by <TT><FONT FACE="Courier">ptr</FONT></TT> to the value in <TT><FONT FACE="Courier">incoming</FONT></TT>.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=295><TT><FONT FACE="Courier">void sv_setsv(SV* dst, SV*src);</FONT></TT>
</TD><TD WIDTH=295>This function sets the value of the <TT><FONT FACE="Courier">SV</FONT></TT> being pointed to by <TT><FONT FACE="Courier">dst</FONT></TT> to the value pointed to by <TT><FONT FACE="Courier">src</FONT></TT> in <TT><FONT
FACE="Courier">incoming</FONT></TT>.
</TD></TR>
</TABLE></CENTER>
<P>
<P>
Perl does not keep <TT><FONT FACE="Courier">NULL</FONT></TT>-terminated
strings like C does. In fact, Perl strings can have multiple <TT><FONT FACE="Courier">NULL</FONT></TT>s
in them. Perl tracks strings by a pointer and the length of the
string. Strings can be modified in one of these ways:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">void sv_setpvn(SV* ptr, char* anyt ,
int len);<BR>
</FONT></TT>This sets the value of the <TT><FONT FACE="Courier">SV</FONT></TT>
being pointed to by <TT><FONT FACE="Courier">ptr</FONT></TT> to
the value in <TT><FONT FACE="Courier">anyt</FONT></TT>. The string
<TT><FONT FACE="Courier">anyt</FONT></TT> contains an array of
<TT><FONT FACE="Courier">char</FONT></TT> items and does not have
to be a <TT><FONT FACE="Courier">NULL</FONT></TT>-terminated string.
In fact, the string <TT><FONT FACE="Courier">anyt</FONT></TT>
can contain <TT><FONT FACE="Courier">NULL</FONT></TT>s because
the function uses the value in <TT><FONT FACE="Courier">len</FONT></TT>
to keep the string in memory.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">void sv_setpv(SV* ptr, char* nullt);
<BR>
</FONT></TT>This sets the value of the <TT><FONT FACE="Courier">SV</FONT></TT>
being pointed to by <TT><FONT FACE="Courier">ptr</FONT></TT> to
the value in <TT><FONT FACE="Courier">nullt</FONT></TT>. The <TT><FONT FACE="Courier">nullt</FONT></TT>
string is a <TT><FONT FACE="Courier">NULL</FONT></TT>-terminated
string like those in C, and the function calculates and sets the
length for you automatically.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SvGROW(SV* ptr, STRLEN newlen);<BR>
</FONT></TT>This function increases the size of a string to the
size in <TT><FONT FACE="Courier">newlen</FONT></TT>. You cannot
decrease the size of a string using this function. Make a new
variable and copy into it. You can use the function <TT><FONT FACE="Courier">SvCUR(SV*)</FONT></TT>
to get the length of a string and <TT><FONT FACE="Courier">SvCUR_set(SV*,
I32 length)</FONT></TT> to set the length of a string.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">void sv_catpv(SV* ptr, char*);<BR>
</FONT></TT>This function appends a <TT><FONT FACE="Courier">NULL</FONT></TT>-terminated
string to a string in <TT><FONT FACE="Courier">SV</FONT></TT>.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">void sv_catpvn(SV* ptr, char*, int);
<BR>
</FONT></TT>This function appends a string of length <TT><FONT FACE="Courier">len</FONT></TT>
to the <TT><FONT FACE="Courier">SV</FONT></TT> pointed at by <TT><FONT FACE="Courier">ptr</FONT></TT>.
</BLOCKQUOTE>
<BLOCKQUOTE>
v<TT><FONT FACE="Courier">oid sv_catsv(SV*dst, SV*src);<BR>
</FONT></TT>This appends another SV* to an SV.
</BLOCKQUOTE>
<P>
Your C program using these programs will crash if you are not
careful enough to check whether these variables exist. To check
whether a scalar variable exists, you can call these functions:
<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=205><TT><FONT FACE="Courier">SvPOK(SV*ptr)</FONT></TT>
</TD><TD WIDTH=150>For string</TD></TR>
<TR VALIGN=TOP><TD WIDTH=205><TT><FONT FACE="Courier">SvIOK(SV*ptr)</FONT></TT>
</TD><TD WIDTH=150>For integer</TD></TR>
<TR VALIGN=TOP><TD WIDTH=205><TT><FONT FACE="Courier">SvNOK(SV*ptr)</FONT></TT>
</TD><TD WIDTH=150>For double</TD></TR>
<TR VALIGN=TOP><TD WIDTH=205><TT><FONT FACE="Courier">SvTRUE(SV *ptr)</FONT></TT>
</TD><TD WIDTH=150>For Boolean value</TD></TR>
</TABLE></CENTER>
<P>
<P>
A value of <TT><FONT FACE="Courier">FALSE</FONT></TT> received
from these functions means that the variable does not exist. You
can only get two returned values, either <TT><FONT FACE="Courier">TRUE</FONT></TT>
or <TT><FONT FACE="Courier">FALSE</FONT></TT>, from the functions
that check whether a variable is a string, integer, or double.
The <TT><FONT FACE="Courier">SvTRUE(SV*)</FONT></TT> macro returns
<TT><FONT FACE="Courier">0</FONT></TT> if the value pointed at
by <TT><FONT FACE="Courier">SV</FONT></TT> is an integer zero
or if <TT><FONT FACE="Courier">SV</FONT></TT> does not exist.
Two other global variables, <TT><FONT FACE="Courier">sv_yes</FONT></TT>
and <TT><FONT FACE="Courier">sv_no</FONT></TT>, can be used instead
of <TT><FONT FACE="Courier">TRUE</FONT></TT> and <TT><FONT FACE="Courier">FALSE</FONT></TT>,
respectively.<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD ><B>Note</B></TD></TR>
<TR VALIGN=TOP><TD >
<BLOCKQUOTE>
The Perl scalar <TT><FONT FACE="Courier">undef</FONT></TT> value is stored in an <TT><FONT FACE="Courier">SV</FONT></TT> instance called <TT><FONT FACE="Courier">sv_undef</FONT></TT>. The <TT><FONT FACE="Courier">sv_undef</FONT></TT> value is not <TT><FONT
FACE="Courier">(SV *) 0</FONT></TT> as you would expect in most versions of C.
</BLOCKQUOTE>
</TD></TR>
</TABLE></CENTER>
<P>
<P>
You can get a pointer to an existing scalar by specifying its
variable name in the call to the function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SV* perl_get_sv("myScalar",
FALSE);</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">FALSE</FONT></TT> parameter requests
the function to return <TT><FONT FACE="Courier">sv_undef</FONT></TT>
if the variable does not exist. If you specify a <TT><FONT FACE="Courier">TRUE</FONT></TT>
value as the second parameter, a new scalar variable is created
for you and assigned the name <TT><FONT FACE="Courier">myScalar</FONT></TT>
in the current name space.
<P>
In fact, you can use package names in the variable name. For example,
the following call creates a variable called <TT><FONT FACE="Courier">desk</FONT></TT>
in the <TT><FONT FACE="Courier">VRML</FONT></TT> package:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SV *desk;<BR>
desk = perl_get_sv("VRML::desk", FALSE);</FONT></TT>
</BLOCKQUOTE>
<P>
Now let's look at collections of scalars: arrays.
<H2><A NAME="ArrayFunctions"><B><FONT SIZE=5 COLOR=#FF0000>Array
Functions</FONT></B></A></H2>
<P>
The functions for handling array variables are similar in operation
to those for scalar variables. To create an array called <TT><FONT FACE="Courier">myarray</FONT></TT>,
you would use this call:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">AV *myarray = (AV* ) newAV();</FONT></TT>
</BLOCKQUOTE>
<P>
To get the array by specifying the name, you can also use the
following function. This <TT><FONT FACE="Courier">perl_get_av()</FONT></TT>
returns <TT><FONT FACE="Courier">NULL</FONT></TT> if the variable
does not exist:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">AV* perl_get_av(char *myarray,
bool makeIt);</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">makeIt</FONT></TT> variable can be
set to <TT><FONT FACE="Courier">TRUE</FONT></TT> if you want the
array created, and <TT><FONT FACE="Courier">FALSE</FONT></TT>
if you are merely checking for its existence and do not want the
array created if it does not exist.
<P>
To initialize an array at the time of creation, you can use the
<TT><FONT FACE="Courier">av_make()</FONT></TT> function. Here's
the syntax for the <TT><FONT FACE="Courier">av_make()</FONT></TT>
function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">AV *myarray = (AV *)av_make(I32
num, SV **data);</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">num</FONT></TT> parameter is the
size of the <TT><FONT FACE="Courier">AV</FONT></TT> array, and
<TT><FONT FACE="Courier">data</FONT></TT> is a pointer to an array
of pointers to scalars to add to this new array called <TT><FONT FACE="Courier">myarray</FONT></TT>.
Do you see how the call uses <I>pointers </I>to <TT><FONT FACE="Courier">SV</FONT></TT>,
rather than <TT><FONT FACE="Courier">SV</FONT></TT>s? The added
level of indirection permits Perl to store any type of <TT><FONT FACE="Courier">SV</FONT></TT>
in an array. So, you can store strings, integers, and doubles
all in one array in Perl. The array passed into the <TT><FONT FACE="Courier">av_make()</FONT></TT>
function is copied into a new memory area; therefore, the original
<TT><FONT FACE="Courier">data</FONT></TT> array does not have
to persist.
<P>
Check the <TT><FONT FACE="Courier">av.c</FONT></TT> source file
in your Perl distribution for more details on the functions and
their parameters. Here is a quick list of the functions you would
most likely perform on <TT><FONT FACE="Courier">AV</FONT></TT>s.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">void av_push(AV *ptr, SV *item);<BR>
</FONT></TT>Pushes an item to the back of an array.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SV* av_pop(AV *ptr);<BR>
</FONT></TT>Pops an item off the back of an array.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SV* av_shift(AV *ptr);<BR>
</FONT></TT>Removes an item from the front of the array.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">void av_unshift(AV *ptr, I32 num);<BR>
</FONT></TT>Inserts <TT><FONT FACE="Courier">num</FONT></TT> items
into the front of the array. The operation in this function only
creates space for you. You still have to call the <TT><FONT FACE="Courier">av_store()</FONT></TT>
function (defined below) to assign values to the newly added items.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">I32 av_len(AV *ptr);<BR>
</FONT></TT>Returns the highest index in array.
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">SV** av_fetch(AV *ptr, I32 offset, I32
lval);<BR>
</FONT></TT>Gets the value in the array at the offset. If <TT><FONT FACE="Courier">lval</FONT></TT>
is a nonzero value, the value at the offset is replaced with the
value of <TT><FONT FACE="Courier">lval</FONT></TT>.
</BLOCKQUOTE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -