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

📄 perlembed.pod

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 POD
📖 第 1 页 / 共 3 页
字号:
Given an C<SV>, a pattern, and a pointer to an empty C<AV>,matches() evaluates C<$string =~ $pattern> in a list context, andfills in I<matches> with the array elements, returning the number of matches found.Here's a sample program, I<match.c>, that uses all three (long lines havebeen wrapped here): #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; /** my_eval_sv(code, error_check) ** kinda like eval_sv(),  ** but we pop the return value off the stack  **/ SV* my_eval_sv(SV *sv, I32 croak_on_error) {     dSP;     SV* retval;     STRLEN n_a;     PUSHMARK(SP);     eval_sv(sv, G_SCALAR);     SPAGAIN;     retval = POPs;     PUTBACK;     if (croak_on_error && SvTRUE(ERRSV)) 	croak(SvPVx(ERRSV, n_a));     return retval; } /** match(string, pattern) ** ** Used for matches in a scalar context. ** ** Returns 1 if the match was successful; 0 otherwise. **/ I32 match(SV *string, char *pattern) {     SV *command = newSV(0), *retval;     STRLEN n_a;     sv_setpvf(command, "my $string = '%s'; $string =~ %s", 	      SvPV(string,n_a), pattern);     retval = my_eval_sv(command, TRUE);     SvREFCNT_dec(command);     return SvIV(retval); } /** substitute(string, pattern) ** ** Used for =~ operations that modify their left-hand side (s/// and tr///) ** ** Returns the number of successful matches, and ** modifies the input string if there were any. **/ I32 substitute(SV **string, char *pattern) {     SV *command = newSV(0), *retval;     STRLEN n_a;     sv_setpvf(command, "$string = '%s'; ($string =~ %s)", 	      SvPV(*string,n_a), pattern);     retval = my_eval_sv(command, TRUE);     SvREFCNT_dec(command);     *string = get_sv("string", FALSE);     return SvIV(retval); } /** matches(string, pattern, matches) ** ** Used for matches in a list context. ** ** Returns the number of matches, ** and fills in **matches with the matching substrings **/ I32 matches(SV *string, char *pattern, AV **match_list) {     SV *command = newSV(0);     I32 num_matches;     STRLEN n_a;     sv_setpvf(command, "my $string = '%s'; @array = ($string =~ %s)", 	      SvPV(string,n_a), pattern);     my_eval_sv(command, TRUE);     SvREFCNT_dec(command);     *match_list = get_av("array", FALSE);     num_matches = av_len(*match_list) + 1; /** assume $[ is 0 **/     return num_matches; } main (int argc, char **argv, char **env) {     char *embedding[] = { "", "-e", "0" };     AV *match_list;     I32 num_matches, i;     SV *text;     STRLEN n_a;     PERL_SYS_INIT3(&argc,&argv,&env);     my_perl = perl_alloc();     perl_construct(my_perl);     perl_parse(my_perl, NULL, 3, embedding, NULL);     PL_exit_flags |= PERL_EXIT_DESTRUCT_END;     text = newSV(0);     sv_setpv(text, "When he is at a convenience store and the "	"bill comes to some amount like 76 cents, Maynard is "	"aware that there is something he *should* do, something "	"that will enable him to get back a quarter, but he has "	"no idea *what*.  He fumbles through his red squeezey "	"changepurse and gives the boy three extra pennies with "	"his dollar, hoping that he might luck into the correct "	"amount.  The boy gives him back two of his own pennies "	"and then the big shiny quarter that is his prize. "	"-RICHH");     if (match(text, "m/quarter/")) /** Does text contain 'quarter'? **/ 	printf("match: Text contains the word 'quarter'.\n\n");     else 	printf("match: Text doesn't contain the word 'quarter'.\n\n");     if (match(text, "m/eighth/")) /** Does text contain 'eighth'? **/ 	printf("match: Text contains the word 'eighth'.\n\n");     else 	printf("match: Text doesn't contain the word 'eighth'.\n\n");     /** Match all occurrences of /wi../ **/     num_matches = matches(text, "m/(wi..)/g", &match_list);     printf("matches: m/(wi..)/g found %d matches...\n", num_matches);     for (i = 0; i < num_matches; i++) 	printf("match: %s\n", SvPV(*av_fetch(match_list, i, FALSE),n_a));     printf("\n");     /** Remove all vowels from text **/     num_matches = substitute(&text, "s/[aeiou]//gi");     if (num_matches) { 	printf("substitute: s/[aeiou]//gi...%d substitutions made.\n", 	       num_matches); 	printf("Now text is: %s\n\n", SvPV(text,n_a));     }     /** Attempt a substitution **/     if (!substitute(&text, "s/Perl/C/")) { 	printf("substitute: s/Perl/C...No substitution made.\n\n");     }     SvREFCNT_dec(text);     PL_perl_destruct_level = 1;     perl_destruct(my_perl);     perl_free(my_perl);     PERL_SYS_TERM(); }which produces the output (again, long lines have been wrapped here)   match: Text contains the word 'quarter'.   match: Text doesn't contain the word 'eighth'.   matches: m/(wi..)/g found 2 matches...   match: will   match: with   substitute: s/[aeiou]//gi...139 substitutions made.   Now text is: Whn h s t  cnvnnc str nd th bll cms t sm mnt lk 76 cnts,   Mynrd s wr tht thr s smthng h *shld* d, smthng tht wll nbl hm t gt bck   qrtr, bt h hs n d *wht*.  H fmbls thrgh hs rd sqzy chngprs nd gvs th by   thr xtr pnns wth hs dllr, hpng tht h mght lck nt th crrct mnt.  Th by gvs   hm bck tw f hs wn pnns nd thn th bg shny qrtr tht s hs prz. -RCHH   substitute: s/Perl/C...No substitution made.=head2 Fiddling with the Perl stack from your C programWhen trying to explain stacks, most computer science textbooks mumblesomething about spring-loaded columns of cafeteria plates: the lastthing you pushed on the stack is the first thing you pop off.  That'lldo for our purposes: your C program will push some arguments onto "the Perlstack", shut its eyes while some magic happens, and then pop theresults--the return value of your Perl subroutine--off the stack.First you'll need to know how to convert between C types and Perltypes, with newSViv() and sv_setnv() and newAV() and all theirfriends.  They're described in L<perlguts> and L<perlapi>.Then you'll need to know how to manipulate the Perl stack.  That'sdescribed in L<perlcall>.Once you've understood those, embedding Perl in C is easy.Because C has no builtin function for integer exponentiation, let'smake Perl's ** operator available to it (this is less useful than itsounds, because Perl implements ** with C's I<pow()> function).  FirstI'll create a stub exponentiation function in I<power.pl>:    sub expo {        my ($a, $b) = @_;        return $a ** $b;    }Now I'll create a C program, I<power.c>, with a functionI<PerlPower()> that contains all the perlguts necessary to push thetwo arguments into I<expo()> and to pop the return value out.  Take adeep breath...    #include <EXTERN.h>    #include <perl.h>    static PerlInterpreter *my_perl;    static void    PerlPower(int a, int b)    {      dSP;                            /* initialize stack pointer      */      ENTER;                          /* everything created after here */      SAVETMPS;                       /* ...is a temporary variable.   */      PUSHMARK(SP);                   /* remember the stack pointer    */      XPUSHs(sv_2mortal(newSViv(a))); /* push the base onto the stack  */      XPUSHs(sv_2mortal(newSViv(b))); /* push the exponent onto stack  */      PUTBACK;                      /* make local stack pointer global */      call_pv("expo", G_SCALAR);      /* call the function             */      SPAGAIN;                        /* refresh stack pointer         */                                    /* pop the return value from stack */      printf ("%d to the %dth power is %d.\n", a, b, POPi);      PUTBACK;      FREETMPS;                       /* free that return value        */      LEAVE;                       /* ...and the XPUSHed "mortal" args.*/    }    int main (int argc, char **argv, char **env)    {      char *my_argv[] = { "", "power.pl" };      PERL_SYS_INIT3(&argc,&argv,&env);      my_perl = perl_alloc();      perl_construct( my_perl );      perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL);      PL_exit_flags |= PERL_EXIT_DESTRUCT_END;      perl_run(my_perl);      PerlPower(3, 4);                      /*** Compute 3 ** 4 ***/      perl_destruct(my_perl);      perl_free(my_perl);      PERL_SYS_TERM();    }Compile and run:    % cc -o power power.c `perl -MExtUtils::Embed -e ccopts -e ldopts`    % power    3 to the 4th power is 81.=head2 Maintaining a persistent interpreterWhen developing interactive and/or potentially long-runningapplications, it's a good idea to maintain a persistent interpreterrather than allocating and constructing a new interpreter multipletimes.  The major reason is speed: since Perl will only be loaded intomemory once.However, you have to be more cautious with namespace and variablescoping when using a persistent interpreter.  In previous exampleswe've been using global variables in the default package C<main>.  Weknew exactly what code would be run, and assumed we could avoidvariable collisions and outrageous symbol table growth.Let's say your application is a server that will occasionally run Perlcode from some arbitrary file.  Your server has no way of knowing whatcode it's going to run.  Very dangerous.If the file is pulled in by C<perl_parse()>, compiled into a newlyconstructed interpreter, and subsequently cleaned out withC<perl_destruct()> afterwards, you're shielded from most namespacetroubles.One way to avoid namespace collisions in this scenario is to translatethe filename into a guaranteed-unique package name, and then compilethe code into that package using L<perlfunc/eval>.  In the examplebelow, each file will only be compiled once.  Or, the applicationmight choose to clean out the symbol table associated with the fileafter it's no longer needed.  Using L<perlapi/call_argv>, We'llcall the subroutine C<Embed::Persistent::eval_file> which lives in thefile C<persistent.pl> and pass the filename and boolean cleanup/cacheflag as arguments.Note that the process will continue to grow for each file that ituses.  In addition, there might be C<AUTOLOAD>ed subroutines and otherconditions that cause Perl's symbol table to grow.  You might want toadd some logic that keeps track of the process size, or restartsitself after a certain number of requests, to ensure that memoryconsumption is minimized.  You'll also want to scope your variableswith L<perlfunc/my> whenever possible. package Embed::Persistent; #persistent.pl use strict; our %Cache; use Symbol qw(delete_package); sub valid_package_name {     my($string) = @_;     $string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg;     # second pass only for words starting with a digit     $string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg;     # Dress it up as a real package name     $string =~ s|/|::|g;     return "Embed" . $string; } sub eval_file {     my($filename, $delete) = @_;     my $package = valid_package_name($filename);     my $mtime = -M $filename;     if(defined $Cache{$package}{mtime}        &&        $Cache{$package}{mtime} <= $mtime)     {        # we have compiled this subroutine already,        # it has not been updated on disk, nothing left to do        print STDERR "already compiled $package->handler\n";     }     else {        local *FH;        open FH, $filename or die "open '$filename' $!";        local($/) = undef;        my $sub = <FH>;        close FH;        #wrap the code into a subroutine inside our unique package        my $eval = qq{package $package; sub handler { $sub; }};        {            # hide our variables within this block            my($filename,$mtime,$package,$sub);            eval $eval;        }        die $@ if $@;        #cache it unless we're cleaning out each time        $Cache{$package}{mtime} = $mtime unless $delete;     }     eval {$package->handler;};     die $@ if $@;     delete_package($package) if $delete;     #take a look if you want     #print Devel::Symdump->rnew($package)->as_string, $/; } 1; __END__ /* persistent.c */ #include <EXTERN.h> #include <perl.h> /* 1 = clean out filename's symbol table after each request, 0 = don't */ #ifndef DO_CLEAN #define DO_CLEAN 0 #endif

⌨️ 快捷键说明

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