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

📄 perlcall.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 5 页
字号:
.Sh "Returning a list in a scalar context".IX Subsection "Returning a list in a scalar context"Say the Perl subroutine in the previous section was called in a scalarcontext, like this.PP.Vb 8\&    static void\&    call_AddSubScalar(a, b)\&    int a;\&    int b;\&    {\&        dSP;\&        int count;\&        int i;\&\&        ENTER;\&        SAVETMPS;\&\&        PUSHMARK(SP);\&        XPUSHs(sv_2mortal(newSViv(a)));\&        XPUSHs(sv_2mortal(newSViv(b)));\&        PUTBACK;\&\&        count = call_pv("AddSubtract", G_SCALAR);\&\&        SPAGAIN;\&\&        printf ("Items Returned = %d\en", count);\&\&        for (i = 1; i <= count; ++i)\&            printf ("Value %d = %d\en", i, POPi);\&\&        PUTBACK;\&        FREETMPS;\&        LEAVE;\&    }.Ve.PPThe other modification made is that \fIcall_AddSubScalar\fR will print thenumber of items returned from the Perl subroutine and their value (forsimplicity it assumes that they are integer).  So if\&\fIcall_AddSubScalar\fR is called.PP.Vb 1\&    call_AddSubScalar(7, 4);.Ve.PPthen the output will be.PP.Vb 2\&    Items Returned = 1\&    Value 1 = 3.Ve.PPIn this case the main point to note is that only the last item in thelist is returned from the subroutine, \fIAddSubtract\fR actually made it back to\&\fIcall_AddSubScalar\fR..Sh "Returning Data from Perl via the parameter list".IX Subsection "Returning Data from Perl via the parameter list"It is also possible to return values directly via the parameter list \-whether it is actually desirable to do it is another matter entirely..PPThe Perl subroutine, \fIInc\fR, below takes 2 parameters and incrementseach directly..PP.Vb 5\&    sub Inc\&    {\&        ++ $_[0];\&        ++ $_[1];\&    }.Ve.PPand here is a C function to call it..PP.Vb 9\&    static void\&    call_Inc(a, b)\&    int a;\&    int b;\&    {\&        dSP;\&        int count;\&        SV * sva;\&        SV * svb;\&\&        ENTER;\&        SAVETMPS;\&\&        sva = sv_2mortal(newSViv(a));\&        svb = sv_2mortal(newSViv(b));\&\&        PUSHMARK(SP);\&        XPUSHs(sva);\&        XPUSHs(svb);\&        PUTBACK;\&\&        count = call_pv("Inc", G_DISCARD);\&\&        if (count != 0)\&            croak ("call_Inc: expected 0 values from \*(AqInc\*(Aq, got %d\en",\&                   count);\&\&        printf ("%d + 1 = %d\en", a, SvIV(sva));\&        printf ("%d + 1 = %d\en", b, SvIV(svb));\&\&        FREETMPS;\&        LEAVE;\&    }.Ve.PPTo be able to access the two parameters that were pushed onto the stackafter they return from \fIcall_pv\fR it is necessary to make a noteof their addresses\*(--thus the two variables \f(CW\*(C`sva\*(C'\fR and \f(CW\*(C`svb\*(C'\fR..PPThe reason this is necessary is that the area of the Perl stack whichheld them will very likely have been overwritten by something else bythe time control returns from \fIcall_pv\fR..Sh "Using G_EVAL".IX Subsection "Using G_EVAL"Now an example using G_EVAL. Below is a Perl subroutine which computesthe difference of its 2 parameters. If this would result in a negativeresult, the subroutine calls \fIdie\fR..PP.Vb 3\&    sub Subtract\&    {\&        my ($a, $b) = @_;\&\&        die "death can be fatal\en" if $a < $b;\&\&        $a \- $b;\&    }.Ve.PPand some C to call it.PP.Vb 7\&    static void\&    call_Subtract(a, b)\&    int a;\&    int b;\&    {\&        dSP;\&        int count;\&\&        ENTER;\&        SAVETMPS;\&\&        PUSHMARK(SP);\&        XPUSHs(sv_2mortal(newSViv(a)));\&        XPUSHs(sv_2mortal(newSViv(b)));\&        PUTBACK;\&\&        count = call_pv("Subtract", G_EVAL|G_SCALAR);\&\&        SPAGAIN;\&\&        /* Check the eval first */\&        if (SvTRUE(ERRSV))\&        {\&            STRLEN n_a;\&            printf ("Uh oh \- %s\en", SvPV(ERRSV, n_a));\&            POPs;\&        }\&        else\&        {\&            if (count != 1)\&               croak("call_Subtract: wanted 1 value from \*(AqSubtract\*(Aq, got %d\en",\&                        count);\&\&            printf ("%d \- %d = %d\en", a, b, POPi);\&        }\&\&        PUTBACK;\&        FREETMPS;\&        LEAVE;\&    }.Ve.PPIf \fIcall_Subtract\fR is called thus.PP.Vb 1\&    call_Subtract(4, 5).Ve.PPthe following will be printed.PP.Vb 1\&    Uh oh \- death can be fatal.Ve.PPNotes.IP "1." 5We want to be able to catch the \fIdie\fR so we have used the G_EVALflag.  Not specifying this flag would mean that the program wouldterminate immediately at the \fIdie\fR statement in the subroutine\&\fISubtract\fR..IP "2." 5The code.Sp.Vb 6\&    if (SvTRUE(ERRSV))\&    {\&        STRLEN n_a;\&        printf ("Uh oh \- %s\en", SvPV(ERRSV, n_a));\&        POPs;\&    }.Ve.Spis the direct equivalent of this bit of Perl.Sp.Vb 1\&    print "Uh oh \- $@\en" if $@;.Ve.Sp\&\f(CW\*(C`PL_errgv\*(C'\fR is a perl global of type \f(CW\*(C`GV *\*(C'\fR that points to thesymbol table entry containing the error.  \f(CW\*(C`ERRSV\*(C'\fR thereforerefers to the C equivalent of \f(CW$@\fR..IP "3." 5Note that the stack is popped using \f(CW\*(C`POPs\*(C'\fR in the block where\&\f(CW\*(C`SvTRUE(ERRSV)\*(C'\fR is true.  This is necessary because whenever a\&\fIcall_*\fR function invoked with G_EVAL|G_SCALAR returns an error,the top of the stack holds the value \fIundef\fR. Because we want theprogram to continue after detecting this error, it is essential thatthe stack is tidied up by removing the \fIundef\fR..Sh "Using G_KEEPERR".IX Subsection "Using G_KEEPERR"Consider this rather facetious example, where we have used an \s-1XS\s0version of the call_Subtract example above inside a destructor:.PP.Vb 9\&    package Foo;\&    sub new { bless {}, $_[0] }\&    sub Subtract {\&        my($a,$b) = @_;\&        die "death can be fatal" if $a < $b;\&        $a \- $b;\&    }\&    sub DESTROY { call_Subtract(5, 4); }\&    sub foo { die "foo dies"; }\&\&    package main;\&    eval { Foo\->new\->foo };\&    print "Saw: $@" if $@;             # should be, but isn\*(Aqt.Ve.PPThis example will fail to recognize that an error occurred inside the\&\f(CW\*(C`eval {}\*(C'\fR.  Here's why: the call_Subtract code got executed while perlwas cleaning up temporaries when exiting the eval block, and becausecall_Subtract is implemented with \fIcall_pv\fR using the G_EVALflag, it promptly reset \f(CW$@\fR.  This results in the failure of theoutermost test for \f(CW$@\fR, and thereby the failure of the error trap..PPAppending the G_KEEPERR flag, so that the \fIcall_pv\fR call incall_Subtract reads:.PP.Vb 1\&        count = call_pv("Subtract", G_EVAL|G_SCALAR|G_KEEPERR);.Ve.PPwill preserve the error and restore reliable error handling..Sh "Using call_sv".IX Subsection "Using call_sv"In all the previous examples I have 'hard\-wired' the name of the Perlsubroutine to be called from C.  Most of the time though, it is moreconvenient to be able to specify the name of the Perl subroutine fromwithin the Perl script..PPConsider the Perl code below.PP.Vb 4\&    sub fred\&    {\&        print "Hello there\en";\&    }\&\&    CallSubPV("fred");.Ve.PPHere is a snippet of \s-1XSUB\s0 which defines \fICallSubPV\fR..PP.Vb 6\&    void\&    CallSubPV(name)\&        char *  name\&        CODE:\&        PUSHMARK(SP);\&        call_pv(name, G_DISCARD|G_NOARGS);.Ve.PPThat is fine as far as it goes. The thing is, the Perl subroutinecan be specified as only a string.  For Perl 4 this was adequate,but Perl 5 allows references to subroutines and anonymous subroutines.This is where \fIcall_sv\fR is useful..PPThe code below for \fICallSubSV\fR is identical to \fICallSubPV\fR exceptthat the \f(CW\*(C`name\*(C'\fR parameter is now defined as an SV* and we use\&\fIcall_sv\fR instead of \fIcall_pv\fR..PP.Vb 6\&    void\&    CallSubSV(name)\&        SV *    name\&        CODE:\&        PUSHMARK(SP);\&        call_sv(name, G_DISCARD|G_NOARGS);.Ve.PPBecause we are using an \s-1SV\s0 to call \fIfred\fR the following can all be used.PP.Vb 5\&    CallSubSV("fred");\&    CallSubSV(\e&fred);\&    $ref = \e&fred;\&    CallSubSV($ref);\&    CallSubSV( sub { print "Hello there\en" } );.Ve.PPAs you can see, \fIcall_sv\fR gives you much greater flexibility inhow you can specify the Perl subroutine..PPYou should note that if it is necessary to store the \s-1SV\s0 (\f(CW\*(C`name\*(C'\fR in theexample above) which corresponds to the Perl subroutine so that it canbe used later in the program, it not enough just to store a copy of thepointer to the \s-1SV\s0. Say the code above had been like this.PP.Vb 1\&    static SV * rememberSub;\&\&    void\&    SaveSub1(name)\&        SV *    name\&        CODE:\&        rememberSub = name;\&\&    void\&    CallSavedSub1()\&        CODE:\&        PUSHMARK(SP);\&        call_sv(rememberSub, G_DISCARD|G_NOARGS);.Ve.PPThe reason this is wrong is that by the time you come to use thepointer \f(CW\*(C`rememberSub\*(C'\fR in \f(CW\*(C`CallSavedSub1\*(C'\fR, it may or may not still referto the Perl subroutine that was recorded in \f(CW\*(C`SaveSub1\*(C'\fR.  This isparticularly true for these cases.PP.Vb 2\&    SaveSub1(\e&fred);\&    CallSavedSub1();\&\&    SaveSub1( sub { print "Hello there\en" } );\&    CallSavedSub1();.Ve.PPBy the time each of the \f(CW\*(C`SaveSub1\*(C'\fR statements above have been executed,the SV*s which corresponded to the parameters will no longer exist.Expect an error message from Perl of the form.PP.Vb 1\&    Can\*(Aqt use an undefined value as a subroutine reference at ....Ve.PPfor each of the \f(CW\*(C`CallSavedSub1\*(C'\fR lines..PPSimilarly, with this code.PP.Vb 4\&    $ref = \e&fred;\&    SaveSub1($ref);\&    $ref = 47;\&    CallSavedSub1();.Ve.PPyou can expect one of these messages (which you actually get is dependent onthe version of Perl you are using).PP.Vb 2\&    Not a CODE reference at ...\&    Undefined subroutine &main::47 called ....Ve.PPThe variable \f(CW$ref\fR may have referred to the subroutine \f(CW\*(C`fred\*(C'\fRwhenever the call to \f(CW\*(C`SaveSub1\*(C'\fR was made but by the time\&\f(CW\*(C`CallSavedSub1\*(C'\fR gets called it now holds the number \f(CW47\fR. Because wesaved only a pointer to the original \s-1SV\s0 in \f(CW\*(C`SaveSub1\*(C'\fR, any changes to\&\f(CW$ref\fR will be tracked by the pointer \f(CW\*(C`rememberSub\*(C'\fR. This means thatwhenever \f(CW\*(C`CallSavedSub1\*(C'\fR gets called, it will attempt to execute thecode which is referenced by the SV* \f(CW\*(C`rememberSub\*(C'\fR.  In this casethough, it now refers to the integer \f(CW47\fR, so expect Perl to complainloudly..PPA similar but more subtle problem is illustrated with this code.PP.Vb 4\&    $ref = \e&fred;\&    SaveSub1($ref);\&    $ref = \e&joe;

⌨️ 快捷键说明

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