⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch25.htm

📁 《Perl 5 Unreleased》
💻 HTM
📖 第 1 页 / 共 4 页
字号:
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*&nbsp;&nbsp;perl_get_sv(&quot;myScalar&quot;,

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 =&nbsp;&nbsp;&nbsp;perl_get_sv(&quot;VRML::desk&quot;, 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*&nbsp;&nbsp;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 =&nbsp;&nbsp;(AV&nbsp;&nbsp;*)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 + -