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

📄 perlcall.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 5 页
字号:
\&    CallSavedSub1();.Ve.PPThis time whenever \f(CW\*(C`CallSavedSub1\*(C'\fR get called it will execute the Perlsubroutine \f(CW\*(C`joe\*(C'\fR (assuming it exists) rather than \f(CW\*(C`fred\*(C'\fR as wasoriginally requested in the call to \f(CW\*(C`SaveSub1\*(C'\fR..PPTo get around these problems it is necessary to take a full copy of the\&\s-1SV\s0.  The code below shows \f(CW\*(C`SaveSub2\*(C'\fR modified to do that.PP.Vb 1\&    static SV * keepSub = (SV*)NULL;\&\&    void\&    SaveSub2(name)\&        SV *    name\&        CODE:\&        /* Take a copy of the callback */\&        if (keepSub == (SV*)NULL)\&            /* First time, so create a new SV */\&            keepSub = newSVsv(name);\&        else\&            /* Been here before, so overwrite */\&            SvSetSV(keepSub, name);\&\&    void\&    CallSavedSub2()\&        CODE:\&        PUSHMARK(SP);\&        call_sv(keepSub, G_DISCARD|G_NOARGS);.Ve.PPTo avoid creating a new \s-1SV\s0 every time \f(CW\*(C`SaveSub2\*(C'\fR is called,the function first checks to see if it has been called before.  If not,then space for a new \s-1SV\s0 is allocated and the reference to the Perlsubroutine, \f(CW\*(C`name\*(C'\fR is copied to the variable \f(CW\*(C`keepSub\*(C'\fR in oneoperation using \f(CW\*(C`newSVsv\*(C'\fR.  Thereafter, whenever \f(CW\*(C`SaveSub2\*(C'\fR is calledthe existing \s-1SV\s0, \f(CW\*(C`keepSub\*(C'\fR, is overwritten with the new value using\&\f(CW\*(C`SvSetSV\*(C'\fR..Sh "Using call_argv".IX Subsection "Using call_argv"Here is a Perl subroutine which prints whatever parameters are passedto it..PP.Vb 3\&    sub PrintList\&    {\&        my(@list) = @_;\&\&        foreach (@list) { print "$_\en" }\&    }.Ve.PPand here is an example of \fIcall_argv\fR which will call\&\fIPrintList\fR..PP.Vb 1\&    static char * words[] = {"alpha", "beta", "gamma", "delta", NULL};\&\&    static void\&    call_PrintList()\&    {\&        dSP;\&\&        call_argv("PrintList", G_DISCARD, words);\&    }.Ve.PPNote that it is not necessary to call \f(CW\*(C`PUSHMARK\*(C'\fR in this instance.This is because \fIcall_argv\fR will do it for you..Sh "Using call_method".IX Subsection "Using call_method"Consider the following Perl code.PP.Vb 2\&    {\&        package Mine;\&\&        sub new\&        {\&            my($type) = shift;\&            bless [@_]\&        }\&\&        sub Display\&        {\&            my ($self, $index) = @_;\&            print "$index: $$self[$index]\en";\&        }\&\&        sub PrintID\&        {\&            my($class) = @_;\&            print "This is Class $class version 1.0\en";\&        }\&    }.Ve.PPIt implements just a very simple class to manage an array.  Apart fromthe constructor, \f(CW\*(C`new\*(C'\fR, it declares methods, one static and onevirtual. The static method, \f(CW\*(C`PrintID\*(C'\fR, prints out simply the classname and a version number. The virtual method, \f(CW\*(C`Display\*(C'\fR, prints out asingle element of the array.  Here is an all Perl example of using it..PP.Vb 3\&    $a = new Mine (\*(Aqred\*(Aq, \*(Aqgreen\*(Aq, \*(Aqblue\*(Aq);\&    $a\->Display(1);\&    PrintID Mine;.Ve.PPwill print.PP.Vb 2\&    1: green\&    This is Class Mine version 1.0.Ve.PPCalling a Perl method from C is fairly straightforward. The followingthings are required.IP "\(bu" 5a reference to the object for a virtual method or the name of the classfor a static method..IP "\(bu" 5the name of the method..IP "\(bu" 5any other parameters specific to the method..PPHere is a simple \s-1XSUB\s0 which illustrates the mechanics of calling boththe \f(CW\*(C`PrintID\*(C'\fR and \f(CW\*(C`Display\*(C'\fR methods from C..PP.Vb 10\&    void\&    call_Method(ref, method, index)\&        SV *    ref\&        char *  method\&        int             index\&        CODE:\&        PUSHMARK(SP);\&        XPUSHs(ref);\&        XPUSHs(sv_2mortal(newSViv(index)));\&        PUTBACK;\&\&        call_method(method, G_DISCARD);\&\&    void\&    call_PrintID(class, method)\&        char *  class\&        char *  method\&        CODE:\&        PUSHMARK(SP);\&        XPUSHs(sv_2mortal(newSVpv(class, 0)));\&        PUTBACK;\&\&        call_method(method, G_DISCARD);.Ve.PPSo the methods \f(CW\*(C`PrintID\*(C'\fR and \f(CW\*(C`Display\*(C'\fR can be invoked like this.PP.Vb 3\&    $a = new Mine (\*(Aqred\*(Aq, \*(Aqgreen\*(Aq, \*(Aqblue\*(Aq);\&    call_Method($a, \*(AqDisplay\*(Aq, 1);\&    call_PrintID(\*(AqMine\*(Aq, \*(AqPrintID\*(Aq);.Ve.PPThe only thing to note is that in both the static and virtual methods,the method name is not passed via the stack\*(--it is used as the firstparameter to \fIcall_method\fR..Sh "Using \s-1GIMME_V\s0".IX Subsection "Using GIMME_V"Here is a trivial \s-1XSUB\s0 which prints the context in which it iscurrently executing..PP.Vb 10\&    void\&    PrintContext()\&        CODE:\&        I32 gimme = GIMME_V;\&        if (gimme == G_VOID)\&            printf ("Context is Void\en");\&        else if (gimme == G_SCALAR)\&            printf ("Context is Scalar\en");\&        else\&            printf ("Context is Array\en");.Ve.PPand here is some Perl to test it.PP.Vb 3\&    PrintContext;\&    $a = PrintContext;\&    @a = PrintContext;.Ve.PPThe output from that will be.PP.Vb 3\&    Context is Void\&    Context is Scalar\&    Context is Array.Ve.Sh "Using Perl to dispose of temporaries".IX Subsection "Using Perl to dispose of temporaries"In the examples given to date, any temporaries created in the callback(i.e., parameters passed on the stack to the \fIcall_*\fR function orvalues returned via the stack) have been freed by one of these methods.IP "\(bu" 5specifying the G_DISCARD flag with \fIcall_*\fR..IP "\(bu" 5explicitly disposed of using the \f(CW\*(C`ENTER\*(C'\fR/\f(CW\*(C`SAVETMPS\*(C'\fR \-\&\f(CW\*(C`FREETMPS\*(C'\fR/\f(CW\*(C`LEAVE\*(C'\fR pairing..PPThere is another method which can be used, namely letting Perl do itfor you automatically whenever it regains control after the callbackhas terminated.  This is done by simply not using the.PP.Vb 5\&    ENTER;\&    SAVETMPS;\&    ...\&    FREETMPS;\&    LEAVE;.Ve.PPsequence in the callback (and not, of course, specifying the G_DISCARDflag)..PPIf you are going to use this method you have to be aware of a possiblememory leak which can arise under very specific circumstances.  Toexplain these circumstances you need to know a bit about the flow ofcontrol between Perl and the callback routine..PPThe examples given at the start of the document (an error handler andan event driven program) are typical of the two main sorts of flowcontrol that you are likely to encounter with callbacks.  There is avery important distinction between them, so pay attention..PPIn the first example, an error handler, the flow of control could be asfollows.  You have created an interface to an external library.Control can reach the external library like this.PP.Vb 1\&    perl \-\-> XSUB \-\-> external library.Ve.PPWhilst control is in the library, an error condition occurs. You havepreviously set up a Perl callback to handle this situation, so it willget executed. Once the callback has finished, control will drop back toPerl again.  Here is what the flow of control will be like in thatsituation.PP.Vb 7\&    perl \-\-> XSUB \-\-> external library\&                      ...\&                      error occurs\&                      ...\&                      external library \-\-> call_* \-\-> perl\&                                                          |\&    perl <\-\- XSUB <\-\- external library <\-\- call_* <\-\-\-\-+.Ve.PPAfter processing of the error using \fIcall_*\fR is completed,control reverts back to Perl more or less immediately..PPIn the diagram, the further right you go the more deeply nested thescope is.  It is only when control is back with perl on the extremeleft of the diagram that you will have dropped back to the enclosingscope and any temporaries you have left hanging around will be freed..PPIn the second example, an event driven program, the flow of controlwill be more like this.PP.Vb 10\&    perl \-\-> XSUB \-\-> event handler\&                      ...\&                      event handler \-\-> call_* \-\-> perl\&                                                       |\&                      event handler <\-\- call_* <\-\-\-\-+\&                      ...\&                      event handler \-\-> call_* \-\-> perl\&                                                       |\&                      event handler <\-\- call_* <\-\-\-\-+\&                      ...\&                      event handler \-\-> call_* \-\-> perl\&                                                       |\&                      event handler <\-\- call_* <\-\-\-\-+.Ve.PPIn this case the flow of control can consist of only the repeatedsequence.PP.Vb 1\&    event handler \-\-> call_* \-\-> perl.Ve.PPfor practically the complete duration of the program.  This means thatcontrol may \fInever\fR drop back to the surrounding scope in Perl at theextreme left..PPSo what is the big problem? Well, if you are expecting Perl to tidy upthose temporaries for you, you might be in for a long wait.  For Perlto dispose of your temporaries, control must drop back to theenclosing scope at some stage.  In the event driven scenario that maynever happen.  This means that as time goes on, your program willcreate more and more temporaries, none of which will ever be freed. Aseach of these temporaries consumes some memory your program willeventually consume all the available memory in your system\*(--kapow!.PPSo here is the bottom line\*(--if you are sure that control will revertback to the enclosing Perl scope fairly quickly after the end of yourcallback, then it isn't absolutely necessary to dispose explicitly ofany temporaries you may have created. Mind you, if you are at alluncertain about what to do, it doesn't do any harm to tidy up anyway..Sh "Strategies for storing Callback Context Information".IX Subsection "Strategies for storing Callback Context Information"Potentially one of the trickiest problems to overcome when designing acallback interface can be figuring out how to store the mapping betweenthe C callback function and the Perl equivalent..PPTo help understand why this can be a real problem first consider how acallback is set up in an all C environment.  Typically a C \s-1API\s0 willprovide a function to register a callback.  This will expect a pointerto a function as one of its parameters.  Below is a call to ahypothetical function \f(CW\*(C`register_fatal\*(C'\fR which registers the C functionto get called when a fatal error occurs..PP.Vb 1\&    register_fatal(cb1);.Ve.PPThe single parameter \f(CW\*(C`cb1\*(C'\fR is a pointer to a function, so you musthave defined \f(CW\*(C`cb1\*(C'\fR in your code, say something like this.PP.Vb 6\&    static void\&    cb1()\&    {\&        printf ("Fatal Error\en");\&        exit(1);\&    }.Ve.PPNow change that to call a Perl subroutine instead.PP.Vb 1\&    static SV * callback = (SV*)NULL;\&\&    static void\&    cb1()\&    {\&        dSP;\&\&        PUSHMARK(SP);\&\&        /* Call the Perl sub to process the callback */\&        call_sv(callback, G_DISCARD);\&    }\&\&\&    void\&    register_fatal(fn)\&        SV *    fn\&        CODE:\&        /* Remember the Perl sub */\&        if (callback == (SV*)NULL)\&            callback = newSVsv(fn);\&        else\&            SvSetSV(callback, fn);\&\&        /* register the callback with the external library */\&        register_fatal(cb1);.Ve.PPwhere the Perl equivalent of \f(CW\*(C`register_fatal\*(C'\fR and the callback itregisters, \f(CW\*(C`pcb1\*(C'\fR, might look like this.PP.Vb 2\&    # Register the sub pcb1\&    register_fatal(\e&pcb1);\&\&    sub pcb1\&    {\&        die "I\*(Aqm dying...\en";\&    }.Ve.PPThe mapping between the C callback and the Perl equivalent is stored inthe global variable \f(CW\*(C`callback\*(C'\fR..PPThis will be adequate if you ever need to have only one callbackregistered at any time. An example could be an error handler like thecode sketched out above. Remember though, repeated calls to\&\f(CW\*(C`register_fatal\*(C'\fR will replace the previously registered callbackfunction with the new one..PPSay for example you want to interface to a library which allows asynchronousfile i/o.  In this case you may be able to register a callback whenevera read operation has completed. To be of any use we want to be able tocall separate Perl subroutines for each file that is opened.  As itstands, the error handler example above would not be adequate as it

⌨️ 快捷键说明

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