📄 ch25.htm
字号:
name of the variable. The <TT><FONT FACE="Courier">SvMAGIC(variable)</FONT></TT>
macro returns the list of methods that are magically applied to
the variable. The <TT><FONT FACE="Courier">SvTYPE()</FONT></TT>
of the variable is <TT><FONT FACE="Courier">SVt_PVMG</FONT></TT>
if it has a list of methods. A normal <TT><FONT FACE="Courier">SV</FONT></TT>
type is upgraded to a magical status by Perl if a method is requested
for it.
<P>
The structure to maintain the list is found in the file <TT><FONT FACE="Courier">mg.h</FONT></TT>
in the Perl source files:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">struct magic {<BR>
MAGIC* mg_moremagic;
<BR>
//
pointer to next method. NULL if none.<BR>
MGVTBL* mg_virtual;
<BR>
// pointer
to table of methods.<BR>
U16 mg_private; //
internal variable<BR>
char mg_type; //
type of methods<BR>
U8 mg_flags; //
flags for this method<BR>
SV* mg_obj; //
Reference to itself<BR>
char* mg_ptr; //
name of the magic variable<BR>
I32 mg_len; //
length of the name<BR>
};</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">mg_type</FONT></TT> value sets up
how the magic function is applied. The following items are used
in the magic table. You can see the values in use in the <TT><FONT FACE="Courier">sv.c</FONT></TT>
file at about line 1950. Table 25.2, which has been constructed
from the <TT><FONT FACE="Courier">switch</FONT></TT> statement,
tells you how methods have to be applied.<BR>
<P>
<CENTER><B>Table 25.2. Types of Magic functions in </B><TT><B><FONT FACE="Courier">mg_type</FONT></B></TT><B>.</B></CENTER>
<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><I><FONT FACE="Courier">Mg_type</FONT></I></TT></CENTER>
</TD><TD WIDTH=166><I>Virtual Magic Table</I></TD><TD WIDTH=209><I>Action Calling Method</I>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">\0</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_sv</FONT></TT>
</TD><TD WIDTH=209>Null operation</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">A</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_amagic</FONT></TT>
</TD><TD WIDTH=209>Operator overloading</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">a</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_amagicelem</FONT></TT>
</TD><TD WIDTH=209>Operator overloading</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">c</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">0</FONT></TT></TD>
<TD WIDTH=209>Used in operator overloading</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">B</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_bm</FONT></TT>
</TD><TD WIDTH=209>Unknown</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">E</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_env</FONT></TT>
</TD><TD WIDTH=209><TT><FONT FACE="Courier">%ENV</FONT></TT> hash
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">e</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_envelem</FONT></TT>
</TD><TD WIDTH=209><TT><FONT FACE="Courier">%ENV</FONT></TT> hash element
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">g</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_mglob</FONT></TT>
</TD><TD WIDTH=209><TT><FONT FACE="Courier">Regexp</FONT></TT> applied globally
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">I</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_isa</FONT></TT>
</TD><TD WIDTH=209><TT><FONT FACE="Courier">@ISA</FONT></TT> array
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">i</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_isaelem</FONT></TT>
</TD><TD WIDTH=209><TT><FONT FACE="Courier">@ISA</FONT></TT> array element
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">L</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">0</FONT></TT></TD>
<TD WIDTH=209>Unknown</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">l</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">tbl_dbline</FONT></TT>
</TD><TD WIDTH=209><TT><FONT FACE="Courier">n</FONT></TT> line debugger
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">P</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">tbl_pack</FONT></TT>
</TD><TD WIDTH=209>Tied array or hash</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">p</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_packelem</FONT></TT>
</TD><TD WIDTH=209>Tied array or hash element</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">q</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_packelem</FONT></TT>
</TD><TD WIDTH=209>Tied scalar or handle</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">S</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_sig</FONT></TT>
</TD><TD WIDTH=209>Signal hash</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">s</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_sigelem</FONT></TT>
</TD><TD WIDTH=209>Signal hash element</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">t</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_taint</FONT></TT>
</TD><TD WIDTH=209>Modified tainted variable</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">U</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_uvar</FONT></TT>
</TD><TD WIDTH=209>Unknown variable type</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">v</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_vec</FONT></TT>
</TD><TD WIDTH=209>Vector</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">x</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_substr</FONT></TT>
</TD><TD WIDTH=209>Substring</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">*</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_glob</FONT></TT>
</TD><TD WIDTH=209>The <TT><FONT FACE="Courier">GV</FONT></TT> type
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier">#</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_arylen</FONT></TT>
</TD><TD WIDTH=209>Array length</TD></TR>
<TR VALIGN=TOP><TD WIDTH=90><CENTER><TT><FONT FACE="Courier"> .</FONT></TT></CENTER>
</TD><TD WIDTH=166><TT><FONT FACE="Courier">vtbl_pos</FONT></TT>
</TD><TD WIDTH=209><TT><FONT FACE="Courier">$.</FONT></TT> scalar variable
</TD></TR>
</TABLE></CENTER>
<P>
<P>
The magic virtual tables are defined in <TT><FONT FACE="Courier">embed.h</FONT></TT>.
The <TT><FONT FACE="Courier">mg_virtual</FONT></TT> field in each
magic entry is assigned to the address of the virtual table.
<P>
Each entry in the magic virtual table has five items, each of
which is defined in the following structure in the file <TT><FONT FACE="Courier">mg.h</FONT></TT>:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">struct mgvtbl {<BR>
int (*svt_get) _((SV
*sv, MAGIC* mg));<BR>
int (*svt_set) _((SV
*sv, MAGIC* mg));<BR>
U32 (*svt_len) _((SV
*sv, MAGIC* mg));<BR>
int (*svt_clear) _((SV
*sv, MAGIC* mg));<BR>
int (*svt_free) _((SV
*sv, MAGIC* mg));<BR>
};</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">svt_get()</FONT></TT> function is
called when the data in <TT><FONT FACE="Courier">SV</FONT></TT>
is retrieved. The <TT><FONT FACE="Courier">svt_set()</FONT></TT>
function is called when the data in <TT><FONT FACE="Courier">SV</FONT></TT>
is stored. The <TT><FONT FACE="Courier">svt_len()</FONT></TT>
function is called when the length of the string is changed. The
<TT><FONT FACE="Courier">svt_clear()</FONT></TT> function is called
when <TT><FONT FACE="Courier">SV</FONT></TT> is cleared, and the
<TT><FONT FACE="Courier">svt_free()</FONT></TT> function is called
when <TT><FONT FACE="Courier">SV</FONT></TT> is destroyed.
<P>
All tables shown in the <TT><FONT FACE="Courier">perl.h</FONT></TT>
file are assigned <TT><FONT FACE="Courier">mgvtbl</FONT></TT>
structures. The values in each <TT><FONT FACE="Courier">mgvtbl</FONT></TT>
structure for each item in a table define a function to call when
an action that affects entries in this table is taken by the Perl
interpreter. Here is an excerpt from the file:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">EXT MGVTBL vtbl_sv =<BR>
{magic_get, magic_set, magic_len,0,0};
<BR>
EXT MGVTBL vtbl_env =<BR>
{0, 0, 0, 0, 0};
<BR>
EXT MGVTBL vtbl_envelem =<BR>
{0, magic_setenv, 0,magic_clearenv,
0};<BR>
EXT MGVTBL vtbl_sig =<BR>
{0, 0, 0, 0, 0};
<BR>
EXT MGVTBL vtbl_sigelem =<BR>
{0, magic_setsig, 0,0,
0};</FONT></TT>
</BLOCKQUOTE>
<P>
The <TT><FONT FACE="Courier">vbtl_sv</FONT></TT> is set to call
three methods: <TT><FONT FACE="Courier">magic_get()</FONT></TT>,
<TT><FONT FACE="Courier">magic_set()</FONT></TT>, and <TT><FONT FACE="Courier">magic_len()</FONT></TT>
for the magic entries in <TT><FONT FACE="Courier">sv</FONT></TT>.
The zeros for <TT><FONT FACE="Courier">vtbl_sig</FONT></TT> indicate
that no magic methods are called.
<H2><A NAME="TheGlobalVariableGVType"><B><FONT SIZE=5 COLOR=#FF0000>The
Global Variable </FONT></B><TT><B><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">(GV)</FONT></B></TT><B><FONT SIZE=5 COLOR=#FF0000>
Type</FONT></B></A></H2>
<P>
If you are still awake, you'll notice a reference to <TT><FONT FACE="Courier">GV</FONT></TT>
in the source file. <TT><FONT FACE="Courier">GV</FONT></TT> stands
for <I>global variable</I>,<I> </I>and the value stored in <TT><FONT FACE="Courier">GV</FONT></TT>
is any data type from scalar to a subroutine reference. <TT><FONT FACE="Courier">GV</FONT></TT>
entries are stored in a hash table, and the keys to each entry
are the names of the symbols being stored. A hash table with <TT><FONT FACE="Courier">GV</FONT></TT>
entries is also referred to as a stash. Internally, a <TT><FONT FACE="Courier">GV</FONT></TT>
type is the same as an <TT><FONT FACE="Courier">HV</FONT></TT>
type.
<P>
Keys in a stash are also package names, with the data item pointing
to other <TT><FONT FACE="Courier">GV</FONT></TT> tables containing
the symbol within the package.
<H2><A NAME="WheretoLookforMoreInformation"><B><FONT SIZE=5 COLOR=#FF0000>Where
to Look for More Information</FONT></B></A></H2>
<P>
Most of the information in this chapter has been gleaned from
source files or the online documents on the Internet. There is
a somewhat old file called <TT><FONT FACE="Courier">perlguts.html</FONT></TT>
by Jeff Okamoto (e-mail <TT><FONT FACE="Courier">okamoto@corp.hp.com</FONT></TT>)
in the <TT><FONT FACE="Courier">www.metronet.com</FONT></TT> archives
that has the Perl API functions and information about the internals.
<P>
Note that the <TT><FONT FACE="Courier">perlguts.html</FONT></TT>
file was dated 1/27/1995, so it's probably not as up-to-date as
you would like.
<P>
Please refer to the <TT><FONT FACE="Courier">perlguts.html</FONT></TT>
or the <TT><FONT FACE="Courier">perlguts</FONT></TT> man page
for a comprehensive listing of the Perl API. If you want a listing
of the functions in the Perl source code and the search strings,
use the <TT><FONT FACE="Courier">ctags *.c</FONT></TT> command
on all the <TT><FONT FACE="Courier">.c</FONT></TT> files in the
Perl source directory. The result will be a very long file (800
lines), called <TT><FONT FACE="Courier">tags</FONT></TT>, in the
same directory. A header of this file is shown here:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">ELSIF perly.c /^"else
: ELSIF '(' expr ')' block else",$/<BR>
GvAVn gv.c /^AV *GvAVn(gv)$/
<BR>
GvHVn gv.c /^HV *GvHVn(gv)$/
<BR>
Gv_AMupdate gv.c /^Gv_AMupdate(stash)$/
<BR>
HTOV util.c /^HTOV(htovs,short)$/<BR>
PP pp.c /^PP(pp_abs)$/<BR>
PP pp.c /^PP(pp_anoncode)$/<BR>
PP pp.c /^PP(pp_anonhash)$/<BR>
PP pp.c /^PP(pp_anonlist)$/<BR>
PP pp.c /^PP(pp_aslice)$/</FONT></TT>
</BLOCKQUOTE>
<P>
If you are a <TT><FONT FACE="Courier">vi</FONT></TT> hack, you
can type <TT><I><FONT FACE="Courier">:tag functionName</FONT></I></TT>
to go to the line and file immediately from within a <TT><FONT FACE="Courier">vi</FONT></TT>
session. Ah, the old <TT><FONT FACE="Courier">vi</FONT></TT> editor
still has a useful function in this day and age. <TT><FONT FACE="Courier">emacs</FONT></TT>
users can issue the command <TT><FONT FACE="Courier">etags *.c</FONT></TT>
and get a comparable <TT><FONT FACE="Courier">tags</FONT></TT>
file for use with the <TT><FONT FACE="Courier">M-x find-tag</FONT></TT>
command in <TT><FONT FACE="Courier">emacs</FONT></TT>.
<H2><A NAME="Summary"><B><FONT SIZE=5 COLOR=#FF0000>Summary</FONT></B></A>
</H2>
<P>
This chapter is a reference-only chapter to prepare you for what
lies ahead in the rest of the book. You'll probably be referring
to this chapter quite a bit as you write <TT><FONT FACE="Courier">include</FONT></TT>
extensions.
<P>
There are three basic types of variables in Perl: <TT><FONT FACE="Courier">SV</FONT></TT>
for scalar, <TT><FONT FACE="Courier">AV</FONT></TT> for arrays,
and <TT><FONT FACE="Courier">HV</FONT></TT> for hash values. Macros
exist for getting data from one type to another. You'll need to
know about these internal data types if you're going to be writing
Perl extensions, dealing with platform-dependent issues, or (ugh)
embedding C code in Perl and vice versa. The dry information in
this chapter will serve you well in the rest of this book.
<P>
<HR WIDTH="100%"></P>
<CENTER><P><A HREF="ch24.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch24.htm"><IMG SRC="pc.gif" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/pc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="#CONTENTS"><IMG SRC="cc.gif" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/cc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="index.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/index.htm"><IMG SRC="hb.gif" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/hb.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="ch26.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch26.htm"><IMG
SRC="nc.gif" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/nc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A></P></CENTER>
<P>
<HR WIDTH="100%"></P>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -