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

📄 perlxstut.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 5 页
字号:
\&            {\&                double  arg = (double)SvNV(ST(0));      /* XXXXX */\&                if (arg > 0.0) {\&                        arg = floor(arg + 0.5);\&                } else if (arg < 0.0) {\&                        arg = ceil(arg \- 0.5);\&                } else {\&                        arg = 0.0;\&                }\&                sv_setnv(ST(0), (double)arg);   /* XXXXX */\&        SvSETMAGIC(ST(0));\&            }\&            XSRETURN_EMPTY;\&        }.Ve.PPNotice the two lines commented with \*(L"\s-1XXXXX\s0\*(R".  If you check the first sectionof the typemap file, you'll see that doubles are of type T_DOUBLE.  In the\&\s-1INPUT\s0 section, an argument that is T_DOUBLE is assigned to the variablearg by calling the routine SvNV on something, then casting it to double,then assigned to the variable arg.  Similarly, in the \s-1OUTPUT\s0 section,once arg has its final value, it is passed to the sv_setnv function tobe passed back to the calling subroutine.  These two functions are explainedin perlguts; we'll talk more later about what that \*(L"\s-1\fIST\s0\fR\|(0)\*(R" means in thesection on the argument stack..Sh "Warning about Output Arguments".IX Subsection "Warning about Output Arguments"In general, it's not a good idea to write extensions that modify their inputparameters, as in Example 3.  Instead, you should probably return multiplevalues in an array and let the caller handle them (we'll do this in a laterexample).  However, in order to better accommodate calling pre-existing Croutines, which often do modify their input parameters, this behavior istolerated..Sh "\s-1EXAMPLE\s0 4".IX Subsection "EXAMPLE 4"In this example, we'll now begin to write XSUBs that will interact withpre-defined C libraries.  To begin with, we will build a small library ofour own, then let h2xs write our .pm and .xs files for us..PPCreate a new directory called Mytest2 at the same level as the directoryMytest.  In the Mytest2 directory, create another directory called mylib,and cd into that directory..PPHere we'll create some files that will generate a test library.  These willinclude a C source file and a header file.  We'll also create a Makefile.PLin this directory.  Then we'll make sure that running make at the Mytest2level will automatically run this Makefile.PL file and the resulting Makefile..PPIn the mylib directory, create a file mylib.h that looks like this:.PP.Vb 1\&        #define TESTVAL 4\&\&        extern double   foo(int, long, const char*);.Ve.PPAlso create a file mylib.c that looks like this:.PP.Vb 2\&        #include <stdlib.h>\&        #include "./mylib.h"\&\&        double\&        foo(int a, long b, const char *c)\&        {\&                return (a + b + atof(c) + TESTVAL);\&        }.Ve.PPAnd finally create a file Makefile.PL that looks like this:.PP.Vb 7\&        use ExtUtils::MakeMaker;\&        $Verbose = 1;\&        WriteMakefile(\&            NAME   => \*(AqMytest2::mylib\*(Aq,\&            SKIP   => [qw(all static static_lib dynamic dynamic_lib)],\&            clean  => {\*(AqFILES\*(Aq => \*(Aqlibmylib$(LIB_EXT)\*(Aq},\&        );\&\&\&        sub MY::top_targets {\&                \*(Aq\&        all :: static\&\&        pure_all :: static\&\&        static ::       libmylib$(LIB_EXT)\&\&        libmylib$(LIB_EXT): $(O_FILES)\&                $(AR) cr libmylib$(LIB_EXT) $(O_FILES)\&                $(RANLIB) libmylib$(LIB_EXT)\&\&        \*(Aq;\&        }.Ve.PPMake sure you use a tab and not spaces on the lines beginning with \*(L"$(\s-1AR\s0)\*(R"and \*(L"$(\s-1RANLIB\s0)\*(R".  Make will not function properly if you use spaces.It has also been reported that the \*(L"cr\*(R" argument to $(\s-1AR\s0) is unnecessaryon Win32 systems..PPWe will now create the main top-level Mytest2 files.  Change to the directoryabove Mytest2 and run the following command:.PP.Vb 1\&        % h2xs \-O \-n Mytest2 ./Mytest2/mylib/mylib.h.Ve.PPThis will print out a warning about overwriting Mytest2, but that's okay.Our files are stored in Mytest2/mylib, and will be untouched..PPThe normal Makefile.PL that h2xs generates doesn't know about the mylibdirectory.  We need to tell it that there is a subdirectory and that wewill be generating a library in it.  Let's add the argument \s-1MYEXTLIB\s0 tothe WriteMakefile call so that it looks like this:.PP.Vb 8\&        WriteMakefile(\&            \*(AqNAME\*(Aq      => \*(AqMytest2\*(Aq,\&            \*(AqVERSION_FROM\*(Aq => \*(AqMytest2.pm\*(Aq, # finds $VERSION\&            \*(AqLIBS\*(Aq      => [\*(Aq\*(Aq],   # e.g., \*(Aq\-lm\*(Aq\&            \*(AqDEFINE\*(Aq    => \*(Aq\*(Aq,     # e.g., \*(Aq\-DHAVE_SOMETHING\*(Aq\&            \*(AqINC\*(Aq       => \*(Aq\*(Aq,     # e.g., \*(Aq\-I/usr/include/other\*(Aq\&            \*(AqMYEXTLIB\*(Aq => \*(Aqmylib/libmylib$(LIB_EXT)\*(Aq,\&        );.Ve.PPand then at the end add a subroutine (which will override the pre-existingsubroutine).  Remember to use a tab character to indent the line beginningwith \*(L"cd\*(R"!.PP.Vb 6\&        sub MY::postamble {\&        \*(Aq\&        $(MYEXTLIB): mylib/Makefile\&                cd mylib && $(MAKE) $(PASSTHRU)\&        \*(Aq;\&        }.Ve.PPLet's also fix the \s-1MANIFEST\s0 file so that it accurately reflects the contentsof our extension.  The single line that says \*(L"mylib\*(R" should be replaced bythe following three lines:.PP.Vb 3\&        mylib/Makefile.PL\&        mylib/mylib.c\&        mylib/mylib.h.Ve.PPTo keep our namespace nice and unpolluted, edit the .pm file and changethe variable \f(CW@EXPORT\fR to \f(CW@EXPORT_OK\fR.  Finally, in the\&.xs file, edit the #include line to read:.PP.Vb 1\&        #include "mylib/mylib.h".Ve.PPAnd also add the following function definition to the end of the .xs file:.PP.Vb 7\&        double\&        foo(a,b,c)\&                int             a\&                long            b\&                const char *    c\&            OUTPUT:\&                RETVAL.Ve.PPNow we also need to create a typemap file because the default Perl doesn'tcurrently support the const char * type.  Create a file called typemap inthe Mytest2 directory and place the following in it:.PP.Vb 1\&        const char *    T_PV.Ve.PPNow run perl on the top-level Makefile.PL.  Notice that it also created aMakefile in the mylib directory.  Run make and watch that it does cd intothe mylib directory and run make in there as well..PPNow edit the Mytest2.t script and change the number of tests to \*(L"4\*(R",and add the following lines to the end of the script:.PP.Vb 3\&        is( &Mytest2::foo(1, 2, "Hello, world!"), 7 );\&        is( &Mytest2::foo(1, 2, "0.0"), 7 );\&        ok( abs(&Mytest2::foo(0, 0, "\-3.4") \- 0.6) <= 0.01 );.Ve.PP(When dealing with floating-point comparisons, it is best to not check forequality, but rather that the difference between the expected and actualresult is below a certain amount (called epsilon) which is 0.01 in this case).PPRun "\f(CW\*(C`make test\*(C'\fR" and all should be well. There are some warnings on missing testsfor the Mytest2::mylib extension, but you can ignore them..Sh "What has happened here?".IX Subsection "What has happened here?"Unlike previous examples, we've now run h2xs on a real include file.  Thishas caused some extra goodies to appear in both the .pm and .xs files..IP "\(bu" 4In the .xs file, there's now a #include directive with the absolute path tothe mylib.h header file.  We changed this to a relative path so that wecould move the extension directory if we wanted to..IP "\(bu" 4There's now some new C code that's been added to the .xs file.  The purposeof the \f(CW\*(C`constant\*(C'\fR routine is to make the values that are #define'd in theheader file accessible by the Perl script (by calling either \f(CW\*(C`TESTVAL\*(C'\fR or\&\f(CW&Mytest2::TESTVAL\fR).  There's also some \s-1XS\s0 code to allow calls to the\&\f(CW\*(C`constant\*(C'\fR routine..IP "\(bu" 4The .pm file originally exported the name \f(CW\*(C`TESTVAL\*(C'\fR in the \f(CW@EXPORT\fR array.This could lead to name clashes.  A good rule of thumb is that if the #defineis only going to be used by the C routines themselves, and not by the user,they should be removed from the \f(CW@EXPORT\fR array.  Alternately, if you don'tmind using the \*(L"fully qualified name\*(R" of a variable, you could move mostor all of the items from the \f(CW@EXPORT\fR array into the \f(CW@EXPORT_OK\fR array..IP "\(bu" 4If our include file had contained #include directives, these would not havebeen processed by h2xs.  There is no good solution to this right now..IP "\(bu" 4We've also told Perl about the library that we built in the mylibsubdirectory.  That required only the addition of the \f(CW\*(C`MYEXTLIB\*(C'\fR variableto the WriteMakefile call and the replacement of the postamble subroutineto cd into the subdirectory and run make.  The Makefile.PL for thelibrary is a bit more complicated, but not excessively so.  Again wereplaced the postamble subroutine to insert our own code.  This codesimply specified that the library to be created here was a static archivelibrary (as opposed to a dynamically loadable library) and provided thecommands to build it..Sh "Anatomy of .xs file".IX Subsection "Anatomy of .xs file"The .xs file of \*(L"\s-1EXAMPLE\s0 4\*(R" contained some new elements.  To understandthe meaning of these elements, pay attention to the line which reads.PP.Vb 1\&        MODULE = Mytest2                PACKAGE = Mytest2.Ve.PPAnything before this line is plain C code which describes which headersto include, and defines some convenience functions.  No translations areperformed on this part, apart from having embedded \s-1POD\s0 documentationskipped over (see perlpod) it goes into the generated output C file as is..PPAnything after this line is the description of \s-1XSUB\s0 functions.These descriptions are translated by \fBxsubpp\fR into C code whichimplements these functions using Perl calling conventions, and whichmakes these functions visible from Perl interpreter..PPPay a special attention to the function \f(CW\*(C`constant\*(C'\fR.  This name appearstwice in the generated .xs file: once in the first part, as a static Cfunction, then another time in the second part, when an \s-1XSUB\s0 interface tothis static C function is defined..PPThis is quite typical for .xs files: usually the .xs file providesan interface to an existing C function.  Then this C function is definedsomewhere (either in an external library, or in the first part of .xs file),and a Perl interface to this function (i.e. \*(L"Perl glue\*(R") is described in thesecond part of .xs file.  The situation in \*(L"\s-1EXAMPLE\s0 1\*(R", \*(L"\s-1EXAMPLE\s0 2\*(R",and \*(L"\s-1EXAMPLE\s0 3\*(R", when all the work is done inside the \*(L"Perl glue\*(R", issomewhat of an exception rather than the rule..Sh "Getting the fat out of XSUBs".IX Subsection "Getting the fat out of XSUBs"In \*(L"\s-1EXAMPLE\s0 4\*(R" the second part of .xs file contained the followingdescription of an \s-1XSUB:\s0.PP.Vb 7\&        double\&        foo(a,b,c)\&                int             a\&                long            b\&                const char *    c\&            OUTPUT:\&                RETVAL.Ve.PPNote that in contrast with \*(L"\s-1EXAMPLE\s0 1\*(R", \*(L"\s-1EXAMPLE\s0 2\*(R" and \*(L"\s-1EXAMPLE\s0 3\*(R",this description does not contain the actual \fIcode\fR for what is doneis done during a call to Perl function \fIfoo()\fR.  To understand what is goingon here, one can add a \s-1CODE\s0 section to this \s-1XSUB:\s0.PP.Vb 9\&        double\&        foo(a,b,c)\&                int             a\&                long            b\&                const char *    c\&            CODE:\&                RETVAL = foo(a,b,c);\&            OUTPUT:\&                RETVAL.Ve.PPHowever, these two XSUBs provide almost identical generated C code: \fBxsubpp\fRcompiler is smart enough to figure out the \f(CW\*(C`CODE:\*(C'\fR section from the firsttwo lines of the description of \s-1XSUB\s0.  What about \f(CW\*(C`OUTPUT:\*(C'\fR section?  Infact, that is absolutely the same!  The \f(CW\*(C`OUTPUT:\*(C'\fR section can be removedas well, \fIas far as \f(CI\*(C`CODE:\*(C'\fI section or \f(CI\*(C`PPCODE:\*(C'\fI section\fR is notspecified: \fBxsubpp\fR can see that it needs to generate a function callsection, and will autogenerate the \s-1OUTPUT\s0 section too.  Thus one canshortcut the \s-1XSUB\s0 to become:.PP.Vb 5\&        double

⌨️ 快捷键说明

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