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

📄 perlxstut.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 5 页
字号:
.IP "\(bu" 4If we were interested in performance, not in code compactness, in the successbranch we would not use \f(CW\*(C`XPUSHs\*(C'\fR macros, but \f(CW\*(C`PUSHs\*(C'\fR macros, and wouldpre-extend the stack before pushing the return values:.Sp.Vb 1\&        EXTEND(SP, 7);.Ve.SpThe tradeoff is that one needs to calculate the number of return valuesin advance (though overextending the stack will not typically hurtanything but memory consumption)..SpSimilarly, in the failure branch we could use \f(CW\*(C`PUSHs\*(C'\fR \fIwithout\fR extendingthe stack: the Perl function reference comes to an \s-1XSUB\s0 on the stack, thusthe stack is \fIalways\fR large enough to take one return value..Sh "\s-1EXAMPLE\s0 6".IX Subsection "EXAMPLE 6"In this example, we will accept a reference to an array as an inputparameter, and return a reference to an array of hashes.  This willdemonstrate manipulation of complex Perl data types from an \s-1XSUB\s0..PPThis extension is somewhat contrived.  It is based on the code inthe previous example.  It calls the statfs function multiple times,accepting a reference to an array of filenames as input, and returninga reference to an array of hashes containing the data for each of thefilesystems..PPReturn to the Mytest directory and add the following code to the end ofMytest.xs:.PP.Vb 8\&    SV *\&    multi_statfs(paths)\&            SV * paths\&        INIT:\&            AV * results;\&            I32 numpaths = 0;\&            int i, n;\&            struct statfs buf;\&\&            if ((!SvROK(paths))\&                || (SvTYPE(SvRV(paths)) != SVt_PVAV)\&                || ((numpaths = av_len((AV *)SvRV(paths))) < 0))\&            {\&                XSRETURN_UNDEF;\&            }\&            results = (AV *)sv_2mortal((SV *)newAV());\&        CODE:\&            for (n = 0; n <= numpaths; n++) {\&                HV * rh;\&                STRLEN l;\&                char * fn = SvPV(*av_fetch((AV *)SvRV(paths), n, 0), l);\&\&                i = statfs(fn, &buf);\&                if (i != 0) {\&                    av_push(results, newSVnv(errno));\&                    continue;\&                }\&\&                rh = (HV *)sv_2mortal((SV *)newHV());\&\&                hv_store(rh, "f_bavail", 8, newSVnv(buf.f_bavail), 0);\&                hv_store(rh, "f_bfree",  7, newSVnv(buf.f_bfree),  0);\&                hv_store(rh, "f_blocks", 8, newSVnv(buf.f_blocks), 0);\&                hv_store(rh, "f_bsize",  7, newSVnv(buf.f_bsize),  0);\&                hv_store(rh, "f_ffree",  7, newSVnv(buf.f_ffree),  0);\&                hv_store(rh, "f_files",  7, newSVnv(buf.f_files),  0);\&                hv_store(rh, "f_type",   6, newSVnv(buf.f_type),   0);\&\&                av_push(results, newRV((SV *)rh));\&            }\&            RETVAL = newRV((SV *)results);\&        OUTPUT:\&            RETVAL.Ve.PPAnd add the following code to Mytest.t, while incrementing the \*(L"11\*(R"tests to \*(L"13\*(R":.PP.Vb 3\&        $results = Mytest::multi_statfs([ \*(Aq/\*(Aq, \*(Aq/blech\*(Aq ]);\&        ok( ref $results\->[0]) );\&        ok( ! ref $results\->[1] );.Ve.Sh "New Things in this Example".IX Subsection "New Things in this Example"There are a number of new concepts introduced here, described below:.IP "\(bu" 4This function does not use a typemap.  Instead, we declare it as acceptingone SV* (scalar) parameter, and returning an SV* value, and we take care ofpopulating these scalars within the code.  Because we are only returningone value, we don't need a \f(CW\*(C`PPCODE:\*(C'\fR directive \- instead, we use \f(CW\*(C`CODE:\*(C'\fRand \f(CW\*(C`OUTPUT:\*(C'\fR directives..IP "\(bu" 4When dealing with references, it is important to handle them with caution.The \f(CW\*(C`INIT:\*(C'\fR block first checks that\&\f(CW\*(C`SvROK\*(C'\fR returns true, which indicates that paths is a valid reference.  Itthen verifies that the object referenced by paths is an array, using \f(CW\*(C`SvRV\*(C'\fRto dereference paths, and \f(CW\*(C`SvTYPE\*(C'\fR to discover its type.  As an added test,it checks that the array referenced by paths is non-empty, using the \f(CW\*(C`av_len\*(C'\fRfunction (which returns \-1 if the array is empty).  The \s-1XSRETURN_UNDEF\s0 macrois used to abort the \s-1XSUB\s0 and return the undefined value whenever all three ofthese conditions are not met..IP "\(bu" 4We manipulate several arrays in this \s-1XSUB\s0.  Note that an array is representedinternally by an AV* pointer.  The functions and macros for manipulatingarrays are similar to the functions in Perl: \f(CW\*(C`av_len\*(C'\fR returns the highestindex in an AV*, much like $#array; \f(CW\*(C`av_fetch\*(C'\fR fetches a single scalar valuefrom an array, given its index; \f(CW\*(C`av_push\*(C'\fR pushes a scalar value onto theend of the array, automatically extending the array as necessary..SpSpecifically, we read pathnames one at a time from the input array, andstore the results in an output array (results) in the same order.  Ifstatfs fails, the element pushed onto the return array is the value oferrno after the failure.  If statfs succeeds, though, the value pushedonto the return array is a reference to a hash containing some of theinformation in the statfs structure..SpAs with the return stack, it would be possible (and a small performance win)to pre-extend the return array before pushing data into it, since we knowhow many elements we will return:.Sp.Vb 1\&        av_extend(results, numpaths);.Ve.IP "\(bu" 4We are performing only one hash operation in this function, which is storinga new scalar under a key using \f(CW\*(C`hv_store\*(C'\fR.  A hash is represented by an HV*pointer.  Like arrays, the functions for manipulating hashes from an \s-1XSUB\s0mirror the functionality available from Perl.  See perlguts and perlapifor details..IP "\(bu" 4To create a reference, we use the \f(CW\*(C`newRV\*(C'\fR function.  Note that you cancast an AV* or an HV* to type SV* in this case (and many others).  Thisallows you to take references to arrays, hashes and scalars with the samefunction.  Conversely, the \f(CW\*(C`SvRV\*(C'\fR function always returns an SV*, which mayneed to be cast to the appropriate type if it is something other than ascalar (check with \f(CW\*(C`SvTYPE\*(C'\fR)..IP "\(bu" 4At this point, xsubpp is doing very little work \- the differences betweenMytest.xs and Mytest.c are minimal..Sh "\s-1EXAMPLE\s0 7 (Coming Soon)".IX Subsection "EXAMPLE 7 (Coming Soon)"\&\s-1XPUSH\s0 args \s-1AND\s0 set \s-1RETVAL\s0 \s-1AND\s0 assign return value to array.Sh "\s-1EXAMPLE\s0 8 (Coming Soon)".IX Subsection "EXAMPLE 8 (Coming Soon)"Setting $!.Sh "\s-1EXAMPLE\s0 9 Passing open files to XSes".IX Subsection "EXAMPLE 9 Passing open files to XSes"You would think passing files to an \s-1XS\s0 is difficult, with all thetypeglobs and stuff. Well, it isn't..PPSuppose that for some strange reason we need a wrapper around thestandard C library function \f(CW\*(C`fputs()\*(C'\fR. This is all we need:.PP.Vb 4\&        #define PERLIO_NOT_STDIO 0\&        #include "EXTERN.h"\&        #include "perl.h"\&        #include "XSUB.h"\&\&        #include <stdio.h>\&\&        int\&        fputs(s, stream)\&                char *          s\&                FILE *          stream.Ve.PPThe real work is done in the standard typemap..PP\&\fBBut\fR you loose all the fine stuff done by the perlio layers. Thiscalls the stdio function \f(CW\*(C`fputs()\*(C'\fR, which knows nothing about them..PPThe standard typemap offers three variants of PerlIO *:\&\f(CW\*(C`InputStream\*(C'\fR (T_IN), \f(CW\*(C`InOutStream\*(C'\fR (T_INOUT) and \f(CW\*(C`OutputStream\*(C'\fR(T_OUT). A bare \f(CW\*(C`PerlIO *\*(C'\fR is considered a T_INOUT. If it mattersin your code (see below for why it might) #define or typedefone of the specific names and use that as the argument or resulttype in your \s-1XS\s0 file..PPThe standard typemap does not contain PerlIO * before perl 5.7,but it has the three stream variants. Using a PerlIO * directlyis not backwards compatible unless you provide your own typemap..PPFor streams coming \fIfrom\fR perl the main difference is that\&\f(CW\*(C`OutputStream\*(C'\fR will get the output PerlIO * \- which may makea difference on a socket. Like in our example....PPFor streams being handed \fIto\fR perl a new file handle is created(i.e. a reference to a new glob) and associated with the PerlIO *provided. If the read/write state of the PerlIO * is not correct then youmay get errors or warnings from when the file handle is used.So if you opened the PerlIO * as \*(L"w\*(R" it should really be an\&\f(CW\*(C`OutputStream\*(C'\fR if open as \*(L"r\*(R" it should be an \f(CW\*(C`InputStream\*(C'\fR..PPNow, suppose you want to use perlio layers in your \s-1XS\s0. We'll use theperlio \f(CW\*(C`PerlIO_puts()\*(C'\fR function as an example..PPIn the C part of the \s-1XS\s0 file (above the first \s-1MODULE\s0 line) youhave.PP.Vb 3\&        #define OutputStream    PerlIO *\&    or\&        typedef PerlIO *        OutputStream;.Ve.PPAnd this is the \s-1XS\s0 code:.PP.Vb 8\&        int\&        perlioputs(s, stream)\&                char *          s\&                OutputStream    stream\&        CODE:\&                RETVAL = PerlIO_puts(stream, s);\&        OUTPUT:\&                RETVAL.Ve.PPWe have to use a \f(CW\*(C`CODE\*(C'\fR section because \f(CW\*(C`PerlIO_puts()\*(C'\fR has the argumentsreversed compared to \f(CW\*(C`fputs()\*(C'\fR, and we want to keep the arguments the same..PPWanting to explore this thoroughly, we want to use the stdio \f(CW\*(C`fputs()\*(C'\fRon a PerlIO *. This means we have to ask the perlio system for a stdio\&\f(CW\*(C`FILE *\*(C'\fR:.PP.Vb 10\&        int\&        perliofputs(s, stream)\&                char *          s\&                OutputStream    stream\&        PREINIT:\&                FILE *fp = PerlIO_findFILE(stream);\&        CODE:\&                if (fp != (FILE*) 0) {\&                        RETVAL = fputs(s, fp);\&                } else {\&                        RETVAL = \-1;\&                }\&        OUTPUT:\&                RETVAL.Ve.PPNote: \f(CW\*(C`PerlIO_findFILE()\*(C'\fR will search the layers for a stdiolayer. If it can't find one, it will call \f(CW\*(C`PerlIO_exportFILE()\*(C'\fR togenerate a new stdio \f(CW\*(C`FILE\*(C'\fR. Please only call \f(CW\*(C`PerlIO_exportFILE()\*(C'\fR ifyou want a \fInew\fR \f(CW\*(C`FILE\*(C'\fR. It will generate one on each call and push anew stdio layer. So don't call it repeatedly on the samefile. \f(CW\*(C`PerlIO()\*(C'\fR_findFILE will retrieve the stdio layer once it has beengenerated by \f(CW\*(C`PerlIO_exportFILE()\*(C'\fR..PPThis applies to the perlio system only. For versions before 5.7,\&\f(CW\*(C`PerlIO_exportFILE()\*(C'\fR is equivalent to \f(CW\*(C`PerlIO_findFILE()\*(C'\fR..Sh "Troubleshooting these Examples".IX Subsection "Troubleshooting these Examples"As mentioned at the top of this document, if you are having problems withthese example extensions, you might see if any of these help you..IP "\(bu" 4In versions of 5.002 prior to the gamma version, the test script in Example1 will not function properly.  You need to change the \*(L"use lib\*(R" line toread:.Sp.Vb 1\&        use lib \*(Aq./blib\*(Aq;.Ve.IP "\(bu" 4In versions of 5.002 prior to version 5.002b1h, the test.pl file was notautomatically created by h2xs.  This means that you cannot say \*(L"make test\*(R"to run the test script.  You will need to add the following line before the\&\*(L"use extension\*(R" statement:.Sp.Vb 1\&        use lib \*(Aq./blib\*(Aq;.Ve.IP "\(bu" 4In versions 5.000 and 5.001, instead of using the above line, you will needto use the following line:.Sp.Vb 1\&        BEGIN { unshift(@INC, "./blib") }.Ve.IP "\(bu" 4This document assumes that the executable named \*(L"perl\*(R" is Perl version 5.Some systems may have installed Perl version 5 as \*(L"perl5\*(R"..SH "See also".IX Header "See also"For more information, consult perlguts, perlapi, perlxs, perlmod,and perlpod..SH "Author".IX Header "Author"Jeff Okamoto <\fIokamoto@corp.hp.com\fR>.PPReviewed and assisted by Dean Roehrich, Ilya Zakharevich, Andreas Koenig,and Tim Bunce..PPPerlIO material contributed by Lupe Christoph, with some clarificationby Nick Ing-Simmons..PPChanges for h2xs as of Perl 5.8.x by Renee Baecker.Sh "Last Changed".IX Subsection "Last Changed"2007/10/11

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -