📄 perlxstut.1
字号:
\& foo(a,b,c)\& int a\& long b\& const char * c.Ve.PPCan we do the same with an \s-1XSUB\s0.PP.Vb 7\& int\& is_even(input)\& int input\& CODE:\& RETVAL = (input % 2 == 0);\& OUTPUT:\& RETVAL.Ve.PPof \*(L"\s-1EXAMPLE\s0 2\*(R"? To do this, one needs to define a C function \f(CW\*(C`intis_even(int input)\*(C'\fR. As we saw in \*(L"Anatomy of .xs file\*(R", a proper placefor this definition is in the first part of .xs file. In fact a C function.PP.Vb 5\& int\& is_even(int arg)\& {\& return (arg % 2 == 0);\& }.Ve.PPis probably overkill for this. Something as simple as a \f(CW\*(C`#define\*(C'\fR willdo too:.PP.Vb 1\& #define is_even(arg) ((arg) % 2 == 0).Ve.PPAfter having this in the first part of .xs file, the \*(L"Perl glue\*(R" part becomesas simple as.PP.Vb 3\& int\& is_even(input)\& int input.Ve.PPThis technique of separation of the glue part from the workhorse part hasobvious tradeoffs: if you want to change a Perl interface, you need tochange two places in your code. However, it removes a lot of clutter,and makes the workhorse part independent from idiosyncrasies of Perl callingconvention. (In fact, there is nothing Perl-specific in the above description,a different version of \fBxsubpp\fR might have translated this to \s-1TCL\s0 glue orPython glue as well.).Sh "More about \s-1XSUB\s0 arguments".IX Subsection "More about XSUB arguments"With the completion of Example 4, we now have an easy way to simulate somereal-life libraries whose interfaces may not be the cleanest in the world.We shall now continue with a discussion of the arguments passed to the\&\fBxsubpp\fR compiler..PPWhen you specify arguments to routines in the .xs file, you are reallypassing three pieces of information for each argument listed. The firstpiece is the order of that argument relative to the others (first, second,etc). The second is the type of argument, and consists of the typedeclaration of the argument (e.g., int, char*, etc). The third piece isthe calling convention for the argument in the call to the library function..PPWhile Perl passes arguments to functions by reference,C passes arguments by value; to implement a C function which modifies dataof one of the \*(L"arguments\*(R", the actual argument of this C function would bea pointer to the data. Thus two C functions with declarations.PP.Vb 2\& int string_length(char *s);\& int upper_case_char(char *cp);.Ve.PPmay have completely different semantics: the first one may inspect an arrayof chars pointed by s, and the second one may immediately dereference \f(CW\*(C`cp\*(C'\fRand manipulate \f(CW*cp\fR only (using the return value as, say, a successindicator). From Perl one would use these functions ina completely different manner..PPOne conveys this info to \fBxsubpp\fR by replacing \f(CW\*(C`*\*(C'\fR before theargument by \f(CW\*(C`&\*(C'\fR. \f(CW\*(C`&\*(C'\fR means that the argument should be passed to a libraryfunction by its address. The above two function may be XSUB-ified as.PP.Vb 3\& int\& string_length(s)\& char * s\&\& int\& upper_case_char(cp)\& char &cp.Ve.PPFor example, consider:.PP.Vb 4\& int\& foo(a,b)\& char &a\& char * b.Ve.PPThe first Perl argument to this function would be treated as a char and assignedto the variable a, and its address would be passed into the function foo.The second Perl argument would be treated as a string pointer and assigned to thevariable b. The \fIvalue\fR of b would be passed into the function foo. Theactual call to the function foo that \fBxsubpp\fR generates would look like this:.PP.Vb 1\& foo(&a, b);.Ve.PP\&\fBxsubpp\fR will parse the following function argument lists identically:.PP.Vb 3\& char &a\& char&a\& char & a.Ve.PPHowever, to help ease understanding, it is suggested that you place a \*(L"&\*(R"next to the variable name and away from the variable type), and place a\&\*(L"*\*(R" near the variable type, but away from the variable name (as in thecall to foo above). By doing so, it is easy to understand exactly whatwill be passed to the C function \*(-- it will be whatever is in the \*(L"lastcolumn\*(R"..PPYou should take great pains to try to pass the function the type of variableit wants, when possible. It will save you a lot of trouble in the long run..Sh "The Argument Stack".IX Subsection "The Argument Stack"If we look at any of the C code generated by any of the examples exceptexample 1, you will notice a number of references to \s-1ST\s0(n), where n isusually 0. \*(L"\s-1ST\s0\*(R" is actually a macro that points to the n'th argumenton the argument stack. \s-1\fIST\s0\fR\|(0) is thus the first argument on the stack andtherefore the first argument passed to the \s-1XSUB\s0, \s-1\fIST\s0\fR\|(1) is the secondargument, and so on..PPWhen you list the arguments to the \s-1XSUB\s0 in the .xs file, that tells \fBxsubpp\fRwhich argument corresponds to which of the argument stack (i.e., the firstone listed is the first argument, and so on). You invite disaster if youdo not list them in the same order as the function expects them..PPThe actual values on the argument stack are pointers to the values passedin. When an argument is listed as being an \s-1OUTPUT\s0 value, its correspondingvalue on the stack (i.e., \s-1\fIST\s0\fR\|(0) if it was the first argument) is changed.You can verify this by looking at the C code generated for Example 3.The code for the \fIround()\fR \s-1XSUB\s0 routine contains lines that look like this:.PP.Vb 3\& double arg = (double)SvNV(ST(0));\& /* Round the contents of the variable arg */\& sv_setnv(ST(0), (double)arg);.Ve.PPThe arg variable is initially set by taking the value from \s-1\fIST\s0\fR\|(0), then isstored back into \s-1\fIST\s0\fR\|(0) at the end of the routine..PPXSUBs are also allowed to return lists, not just scalars. This must bedone by manipulating stack values \s-1\fIST\s0\fR\|(0), \s-1\fIST\s0\fR\|(1), etc, in a subtlydifferent way. See perlxs for details..PPXSUBs are also allowed to avoid automatic conversion of Perl function argumentsto C function arguments. See perlxs for details. Some people prefermanual conversion by inspecting \f(CWST(i)\fR even in the cases when automaticconversion will do, arguing that this makes the logic of an \s-1XSUB\s0 call clearer.Compare with \*(L"Getting the fat out of XSUBs\*(R" for a similar tradeoff ofa complete separation of \*(L"Perl glue\*(R" and \*(L"workhorse\*(R" parts of an \s-1XSUB\s0..PPWhile experts may argue about these idioms, a novice to Perl guts mayprefer a way which is as little Perl-guts-specific as possible, meaningautomatic conversion and automatic call generation, as in\&\*(L"Getting the fat out of XSUBs\*(R". This approach has the additionalbenefit of protecting the \s-1XSUB\s0 writer from future changes to the Perl \s-1API\s0..Sh "Extending your Extension".IX Subsection "Extending your Extension"Sometimes you might want to provide some extra methods or subroutinesto assist in making the interface between Perl and your extension simpleror easier to understand. These routines should live in the .pm file.Whether they are automatically loaded when the extension itself is loadedor only loaded when called depends on where in the .pm file the subroutinedefinition is placed. You can also consult AutoLoader for an alternateway to store and load your extra subroutines..Sh "Documenting your Extension".IX Subsection "Documenting your Extension"There is absolutely no excuse for not documenting your extension.Documentation belongs in the .pm file. This file will be fed to pod2man,and the embedded documentation will be converted to the manpage format,then placed in the blib directory. It will be copied to Perl'smanpage directory when the extension is installed..PPYou may intersperse documentation and Perl code within the .pm file.In fact, if you want to use method autoloading, you must do this,as the comment inside the .pm file explains..PPSee perlpod for more information about the pod format..Sh "Installing your Extension".IX Subsection "Installing your Extension"Once your extension is complete and passes all its tests, installing itis quite simple: you simply run \*(L"make install\*(R". You will either needto have write permission into the directories where Perl is installed,or ask your system administrator to run the make for you..PPAlternately, you can specify the exact directory to place the extension'sfiles by placing a \*(L"PREFIX=/destination/directory\*(R" after the make install.(or in between the make and install if you have a brain-dead version of make).This can be very useful if you are building an extension that will eventuallybe distributed to multiple systems. You can then just archive the files inthe destination directory and distribute them to your destination systems..Sh "\s-1EXAMPLE\s0 5".IX Subsection "EXAMPLE 5"In this example, we'll do some more work with the argument stack. Theprevious examples have all returned only a single value. We'll nowcreate an extension that returns an array..PPThis extension is very Unix-oriented (struct statfs and the statfs systemcall). If you are not running on a Unix system, you can substitute forstatfs any other function that returns multiple values, you can hard-codevalues to be returned to the caller (although this will be a bit harderto test the error case), or you can simply not do this example. If youchange the \s-1XSUB\s0, be sure to fix the test cases to match the changes..PPReturn to the Mytest directory and add the following code to the end ofMytest.xs:.PP.Vb 6\& void\& statfs(path)\& char * path\& INIT:\& int i;\& struct statfs buf;\&\& PPCODE:\& i = statfs(path, &buf);\& if (i == 0) {\& XPUSHs(sv_2mortal(newSVnv(buf.f_bavail)));\& XPUSHs(sv_2mortal(newSVnv(buf.f_bfree)));\& XPUSHs(sv_2mortal(newSVnv(buf.f_blocks)));\& XPUSHs(sv_2mortal(newSVnv(buf.f_bsize)));\& XPUSHs(sv_2mortal(newSVnv(buf.f_ffree)));\& XPUSHs(sv_2mortal(newSVnv(buf.f_files)));\& XPUSHs(sv_2mortal(newSVnv(buf.f_type)));\& } else {\& XPUSHs(sv_2mortal(newSVnv(errno)));\& }.Ve.PPYou'll also need to add the following code to the top of the .xs file, justafter the include of \*(L"\s-1XSUB\s0.h\*(R":.PP.Vb 1\& #include <sys/vfs.h>.Ve.PPAlso add the following code segment to Mytest.t while incrementing the \*(L"9\*(R"tests to \*(L"11\*(R":.PP.Vb 4\& @a = &Mytest::statfs("/blech");\& ok( scalar(@a) == 1 && $a[0] == 2 );\& @a = &Mytest::statfs("/");\& is( scalar(@a), 7 );.Ve.Sh "New Things in this Example".IX Subsection "New Things in this Example"This example added quite a few new concepts. We'll take them one at a time..IP "\(bu" 4The \s-1INIT:\s0 directive contains code that will be placed immediately afterthe argument stack is decoded. C does not allow variable declarations atarbitrary locations inside a function,so this is usually the best way to declare local variables needed by the \s-1XSUB\s0.(Alternatively, one could put the whole \f(CW\*(C`PPCODE:\*(C'\fR section into braces, andput these declarations on top.).IP "\(bu" 4This routine also returns a different number of arguments depending on thesuccess or failure of the call to statfs. If there is an error, the errornumber is returned as a single-element array. If the call is successful,then a 9\-element array is returned. Since only one argument is passed intothis function, we need room on the stack to hold the 9 values which may bereturned..SpWe do this by using the \s-1PPCODE:\s0 directive, rather than the \s-1CODE:\s0 directive.This tells \fBxsubpp\fR that we will be managing the return values that will beput on the argument stack by ourselves..IP "\(bu" 4When we want to place values to be returned to the caller onto the stack,we use the series of macros that begin with \*(L"\s-1XPUSH\s0\*(R". There are fivedifferent versions, for placing integers, unsigned integers, doubles,strings, and Perl scalars on the stack. In our example, we placed aPerl scalar onto the stack. (In fact this is the only macro whichcan be used to return multiple values.).SpThe XPUSH* macros will automatically extend the return stack to preventit from being overrun. You push values onto the stack in the order youwant them seen by the calling program..IP "\(bu" 4The values pushed onto the return stack of the \s-1XSUB\s0 are actually mortal \s-1SV\s0's.They are made mortal so that once the values are copied by the callingprogram, the \s-1SV\s0's that held the returned values can be deallocated.If they were not mortal, then they would continue to exist after the \s-1XSUB\s0routine returned, but would not be accessible. This is a memory leak.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -