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

📄 perlcall.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 5 页
字号:
from the stack..PPSee \fIUsing G_EVAL\fR for details on using G_EVAL..Sh "G_KEEPERR".IX Subsection "G_KEEPERR"You may have noticed that using the G_EVAL flag described above will\&\fBalways\fR clear the \f(CW$@\fR variable and set it to a string describingthe error iff there was an error in the called code.  This unqualifiedresetting of \f(CW$@\fR can be problematic in the reliable identification oferrors using the \f(CW\*(C`eval {}\*(C'\fR mechanism, because the possibility existsthat perl will call other code (end of block processing code, forexample) between the time the error causes \f(CW$@\fR to be set within\&\f(CW\*(C`eval {}\*(C'\fR, and the subsequent statement which checks for the value of\&\f(CW$@\fR gets executed in the user's script..PPThis scenario will mostly be applicable to code that is meant to becalled from within destructors, asynchronous callbacks, signalhandlers, \f(CW\*(C`_\|_DIE_\|_\*(C'\fR or \f(CW\*(C`_\|_WARN_\|_\*(C'\fR hooks, and \f(CW\*(C`tie\*(C'\fR functions.  Insuch situations, you will not want to clear \f(CW$@\fR at all, but simply toappend any new errors to any existing value of \f(CW$@\fR..PPThe G_KEEPERR flag is meant to be used in conjunction with G_EVAL in\&\fIcall_*\fR functions that are used to implement such code.  This flaghas no effect when G_EVAL is not used..PPWhen G_KEEPERR is used, any errors in the called code will be prefixedwith the string \*(L"\et(in cleanup)\*(R", and appended to the current valueof \f(CW$@\fR.  an error will not be appended if that same error string isalready at the end of \f(CW$@\fR..PPIn addition, a warning is generated using the appended string. This can bedisabled using \f(CW\*(C`no warnings \*(Aqmisc\*(Aq\*(C'\fR..PPThe G_KEEPERR flag was introduced in Perl version 5.002..PPSee \fIUsing G_KEEPERR\fR for an example of a situation that warrants theuse of this flag..Sh "Determining the Context".IX Subsection "Determining the Context"As mentioned above, you can determine the context of the currentlyexecuting subroutine in Perl with \fIwantarray\fR.  The equivalent testcan be made in C by using the \f(CW\*(C`GIMME_V\*(C'\fR macro, which returns\&\f(CW\*(C`G_ARRAY\*(C'\fR if you have been called in a list context, \f(CW\*(C`G_SCALAR\*(C'\fR ifin a scalar context, or \f(CW\*(C`G_VOID\*(C'\fR if in a void context (i.e. thereturn value will not be used).  An older version of this macro iscalled \f(CW\*(C`GIMME\*(C'\fR; in a void context it returns \f(CW\*(C`G_SCALAR\*(C'\fR instead of\&\f(CW\*(C`G_VOID\*(C'\fR.  An example of using the \f(CW\*(C`GIMME_V\*(C'\fR macro is shown insection \fIUsing \s-1GIMME_V\s0\fR..SH "EXAMPLES".IX Header "EXAMPLES"Enough of the definition talk, let's have a few examples..PPPerl provides many macros to assist in accessing the Perl stack.Wherever possible, these macros should always be used when interfacingto Perl internals.  We hope this should make the code less vulnerableto any changes made to Perl in the future..PPAnother point worth noting is that in the first series of examples Ihave made use of only the \fIcall_pv\fR function.  This has been doneto keep the code simpler and ease you into the topic.  Whereverpossible, if the choice is between using \fIcall_pv\fR and\&\fIcall_sv\fR, you should always try to use \fIcall_sv\fR.  See\&\fIUsing call_sv\fR for details..Sh "No Parameters, Nothing returned".IX Subsection "No Parameters, Nothing returned"This first trivial example will call a Perl subroutine, \fIPrintUID\fR, toprint out the \s-1UID\s0 of the process..PP.Vb 4\&    sub PrintUID\&    {\&        print "UID is $<\en";\&    }.Ve.PPand here is a C function to call it.PP.Vb 4\&    static void\&    call_PrintUID()\&    {\&        dSP;\&\&        PUSHMARK(SP);\&        call_pv("PrintUID", G_DISCARD|G_NOARGS);\&    }.Ve.PPSimple, eh..PPA few points to note about this example..IP "1." 5Ignore \f(CW\*(C`dSP\*(C'\fR and \f(CW\*(C`PUSHMARK(SP)\*(C'\fR for now. They will be discussed inthe next example..IP "2." 5We aren't passing any parameters to \fIPrintUID\fR so G_NOARGS can bespecified..IP "3." 5We aren't interested in anything returned from \fIPrintUID\fR, soG_DISCARD is specified. Even if \fIPrintUID\fR was changed toreturn some value(s), having specified G_DISCARD will mean that theywill be wiped by the time control returns from \fIcall_pv\fR..IP "4." 5As \fIcall_pv\fR is being used, the Perl subroutine is specified as aC string. In this case the subroutine name has been 'hard\-wired' into thecode..IP "5." 5Because we specified G_DISCARD, it is not necessary to check the valuereturned from \fIcall_pv\fR. It will always be 0..Sh "Passing Parameters".IX Subsection "Passing Parameters"Now let's make a slightly more complex example. This time we want tocall a Perl subroutine, \f(CW\*(C`LeftString\*(C'\fR, which will take 2 parameters\*(--astring ($s) and an integer ($n).  The subroutine will simplyprint the first \f(CW$n\fR characters of the string..PPSo the Perl subroutine would look like this.PP.Vb 5\&    sub LeftString\&    {\&        my($s, $n) = @_;\&        print substr($s, 0, $n), "\en";\&    }.Ve.PPThe C function required to call \fILeftString\fR would look like this..PP.Vb 6\&    static void\&    call_LeftString(a, b)\&    char * a;\&    int b;\&    {\&        dSP;\&\&        ENTER;\&        SAVETMPS;\&\&        PUSHMARK(SP);\&        XPUSHs(sv_2mortal(newSVpv(a, 0)));\&        XPUSHs(sv_2mortal(newSViv(b)));\&        PUTBACK;\&\&        call_pv("LeftString", G_DISCARD);\&\&        FREETMPS;\&        LEAVE;\&    }.Ve.PPHere are a few notes on the C function \fIcall_LeftString\fR..IP "1." 5Parameters are passed to the Perl subroutine using the Perl stack.This is the purpose of the code beginning with the line \f(CW\*(C`dSP\*(C'\fR andending with the line \f(CW\*(C`PUTBACK\*(C'\fR.  The \f(CW\*(C`dSP\*(C'\fR declares a local copyof the stack pointer.  This local copy should \fBalways\fR be accessedas \f(CW\*(C`SP\*(C'\fR..IP "2." 5If you are going to put something onto the Perl stack, you need to knowwhere to put it. This is the purpose of the macro \f(CW\*(C`dSP\*(C'\fR\-\-it declaresand initializes a \fIlocal\fR copy of the Perl stack pointer..SpAll the other macros which will be used in this example require you tohave used this macro..SpThe exception to this rule is if you are calling a Perl subroutinedirectly from an \s-1XSUB\s0 function. In this case it is not necessary touse the \f(CW\*(C`dSP\*(C'\fR macro explicitly\*(--it will be declared for youautomatically..IP "3." 5Any parameters to be pushed onto the stack should be bracketed by the\&\f(CW\*(C`PUSHMARK\*(C'\fR and \f(CW\*(C`PUTBACK\*(C'\fR macros.  The purpose of these two macros, inthis context, is to count the number of parameters you arepushing automatically.  Then whenever Perl is creating the \f(CW@_\fR array for thesubroutine, it knows how big to make it..SpThe \f(CW\*(C`PUSHMARK\*(C'\fR macro tells Perl to make a mental note of the currentstack pointer. Even if you aren't passing any parameters (like theexample shown in the section \fINo Parameters, Nothing returned\fR) youmust still call the \f(CW\*(C`PUSHMARK\*(C'\fR macro before you can call any of the\&\fIcall_*\fR functions\*(--Perl still needs to know that there are noparameters..SpThe \f(CW\*(C`PUTBACK\*(C'\fR macro sets the global copy of the stack pointer to bethe same as our local copy. If we didn't do this \fIcall_pv\fRwouldn't know where the two parameters we pushed were\*(--remember thatup to now all the stack pointer manipulation we have done is with ourlocal copy, \fInot\fR the global copy..IP "4." 5Next, we come to XPUSHs. This is where the parameters actually getpushed onto the stack. In this case we are pushing a string and aninteger..SpSee \*(L"XSUBs and the Argument Stack\*(R" in perlguts for detailson how the \s-1XPUSH\s0 macros work..IP "5." 5Because we created temporary values (by means of \fIsv_2mortal()\fR calls)we will have to tidy up the Perl stack and dispose of mortal SVs..SpThis is the purpose of.Sp.Vb 2\&    ENTER;\&    SAVETMPS;.Ve.Spat the start of the function, and.Sp.Vb 2\&    FREETMPS;\&    LEAVE;.Ve.Spat the end. The \f(CW\*(C`ENTER\*(C'\fR/\f(CW\*(C`SAVETMPS\*(C'\fR pair creates a boundary for anytemporaries we create.  This means that the temporaries we get rid ofwill be limited to those which were created after these calls..SpThe \f(CW\*(C`FREETMPS\*(C'\fR/\f(CW\*(C`LEAVE\*(C'\fR pair will get rid of any values returned bythe Perl subroutine (see next example), plus it will also dump themortal SVs we have created.  Having \f(CW\*(C`ENTER\*(C'\fR/\f(CW\*(C`SAVETMPS\*(C'\fR at thebeginning of the code makes sure that no other mortals are destroyed..SpThink of these macros as working a bit like using \f(CW\*(C`{\*(C'\fR and \f(CW\*(C`}\*(C'\fR in Perlto limit the scope of local variables..SpSee the section \fIUsing Perl to dispose of temporaries\fR for details ofan alternative to using these macros..IP "6." 5Finally, \fILeftString\fR can now be called via the \fIcall_pv\fR function.The only flag specified this time is G_DISCARD. Because we are passing2 parameters to the Perl subroutine this time, we have not specifiedG_NOARGS..Sh "Returning a Scalar".IX Subsection "Returning a Scalar"Now for an example of dealing with the items returned from a Perlsubroutine..PPHere is a Perl subroutine, \fIAdder\fR, that takes 2 integer parametersand simply returns their sum..PP.Vb 5\&    sub Adder\&    {\&        my($a, $b) = @_;\&        $a + $b;\&    }.Ve.PPBecause we are now concerned with the return value from \fIAdder\fR, the Cfunction required to call it is now a bit more complex..PP.Vb 7\&    static void\&    call_Adder(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("Adder", G_SCALAR);\&\&        SPAGAIN;\&\&        if (count != 1)\&            croak("Big trouble\en");\&\&        printf ("The sum of %d and %d is %d\en", a, b, POPi);\&\&        PUTBACK;\&        FREETMPS;\&        LEAVE;\&    }.Ve.PPPoints to note this time are.IP "1." 5The only flag specified this time was G_SCALAR. That means the \f(CW@_\fRarray will be created and that the value returned by \fIAdder\fR willstill exist after the call to \fIcall_pv\fR..IP "2." 5The purpose of the macro \f(CW\*(C`SPAGAIN\*(C'\fR is to refresh the local copy of thestack pointer. This is necessary because it is possible that the memoryallocated to the Perl stack has been reallocated whilst in the\&\fIcall_pv\fR call..SpIf you are making use of the Perl stack pointer in your code you mustalways refresh the local copy using \s-1SPAGAIN\s0 whenever you make useof the \fIcall_*\fR functions or any other Perl internal function..IP "3." 5Although only a single value was expected to be returned from \fIAdder\fR,it is still good practice to check the return code from \fIcall_pv\fRanyway..SpExpecting a single value is not quite the same as knowing that therewill be one. If someone modified \fIAdder\fR to return a list and wedidn't check for that possibility and take appropriate action the Perlstack would end up in an inconsistent state. That is something you\&\fIreally\fR don't want to happen ever..IP "4." 5The \f(CW\*(C`POPi\*(C'\fR macro is used here to pop the return value from the stack.In this case we wanted an integer, so \f(CW\*(C`POPi\*(C'\fR was used..SpHere is the complete list of \s-1POP\s0 macros available, along with the typesthey return..Sp.Vb 5\&    POPs        SV\&    POPp        pointer\&    POPn        double\&    POPi        integer\&    POPl        long.Ve.IP "5." 5The final \f(CW\*(C`PUTBACK\*(C'\fR is used to leave the Perl stack in a consistentstate before exiting the function.  This is necessary because when wepopped the return value from the stack with \f(CW\*(C`POPi\*(C'\fR it updated only ourlocal copy of the stack pointer.  Remember, \f(CW\*(C`PUTBACK\*(C'\fR sets the globalstack pointer to be the same as our local copy..Sh "Returning a list of values".IX Subsection "Returning a list of values"Now, let's extend the previous example to return both the sum of theparameters and the difference..PPHere is the Perl subroutine.PP.Vb 5\&    sub AddSubtract\&    {\&       my($a, $b) = @_;\&       ($a+$b, $a\-$b);\&    }.Ve.PPand this is the C function.PP.Vb 7\&    static void\&    call_AddSubtract(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("AddSubtract", G_ARRAY);\&\&        SPAGAIN;\&\&        if (count != 2)\&            croak("Big trouble\en");\&\&        printf ("%d \- %d = %d\en", a, b, POPi);\&        printf ("%d + %d = %d\en", a, b, POPi);\&\&        PUTBACK;\&        FREETMPS;\&        LEAVE;\&    }.Ve.PPIf \fIcall_AddSubtract\fR is called like this.PP.Vb 1\&    call_AddSubtract(7, 4);.Ve.PPthen here is the output.PP.Vb 2\&    7 \- 4 = 3\&    7 + 4 = 11.Ve.PPNotes.IP "1." 5We wanted list context, so G_ARRAY was used..IP "2." 5Not surprisingly \f(CW\*(C`POPi\*(C'\fR is used twice this time because we wereretrieving 2 values from the stack. The important thing to note is thatwhen using the \f(CW\*(C`POP*\*(C'\fR macros they come off the stack in \fIreverse\fRorder.

⌨️ 快捷键说明

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