=encoding utf-8

=head1 NAME

=head1 名称

perlxs - XS language reference manual

perlxs - XS 语言参考手册

=head1 DESCRIPTION

=head1 描述

=head2 Introduction

=head2 介绍

XS is an interface description file format used to create an extension
interface between Perl and C code (or a C library) which one wishes
to use with Perl.  The XS interface is combined with the library to
create a new library which can then be either dynamically loaded
or statically linked into perl.  The XS interface description is
written in the XS language and is the core component of the Perl
extension interface.

XS 是一种接口描述文件格式,用于创建用于Perl中的Perl与C代码(或C库)的接口。
XS接口与原有的库被联合在一起以创建一个新的库被perl动态加载,或被静态链接到perl中。
XS接口描述是用XS语言写的,是Perl拓展接口的核心组成部分。

An B<XSUB> forms the basic unit of the XS interface.  After compilation
by the B<xsubpp> compiler, each XSUB amounts to a C function definition
which will provide the glue between Perl calling conventions and C
calling conventions.

一个B<XSUB>形成了最基本的XS接口单元。在通过B<xsubpp>编译器编译后,
每一个XSUB对应一个C函数定义,它提供了粘合Perl调用约定与C调用约定的胶水代码。

The glue code pulls the arguments from the Perl stack, converts these
Perl values to the formats expected by a C function, call this C function,
transfers the return values of the C function back to Perl.
Return values here may be a conventional C return value or any C
function arguments that may serve as output parameters.  These return
values may be passed back to Perl either by putting them on the
Perl stack, or by modifying the arguments supplied from the Perl side.

这些胶水代码将参数从Perl栈上取出来,将这些Perl的值转为C函数期望的形式,
调用C函数,将C函数结果返回给Perl。
这里的返回值可以是一个常规的C返回值,或者任何作为出参的参数。
这些返回值可能通过放到Perl栈上的方式,或者修改Perl提供的参数的方式被传回。

The above is a somewhat simplified view of what really happens.  Since
Perl allows more flexible calling conventions than C, XSUBs may do much
more in practice, such as checking input parameters for validity,
throwing exceptions (or returning undef/empty list) if the return value
from the C function indicates failure, calling different C functions
based on numbers and types of the arguments, providing an object-oriented
interface, etc.

以上内容是实际发生的事的简单描述。由于Perl允许比C更加灵活的调用约定,
XSUBs可能会在实践中做更多的工作,比如检查输入参数的合法性,
在C函数返回失败的情况下抛异常(或返回undef/empty列表),
根据参数的数量和类型调用不同的C函数,提供面向对象的结构,等等。

Of course, one could write such glue code directly in C.  However, this
would be a tedious task, especially if one needs to write glue for
multiple C functions, and/or one is not familiar enough with the Perl
stack discipline and other such arcana.  XS comes to the rescue here:
instead of writing this glue C code in long-hand, one can write
a more concise short-hand I<description> of what should be done by
the glue, and let the XS compiler B<xsubpp> handle the rest.

当然,也可以直接用C写胶水代码。但是,这将是非常麻烦的任务,
尤其是当你需要为多个C函数写胶水代码,或者你对Perl栈的特点等诸如此类的的知识不熟悉的话。
XS将为你解决这些问题:你可以写一段更加精确简洁的,关于胶水代码应该做什么的I<描述>,
并让XS 编译器 B<xsubpp>来完成剩下的工作。

The XS language allows one to describe the mapping between how the C
routine is used, and how the corresponding Perl routine is used.  It
also allows creation of Perl routines which are directly translated to
C code and which are not related to a pre-existing C function.  In cases
when the C interface coincides with the Perl interface, the XSUB
declaration is almost identical to a declaration of a C function (in K&R
style).  In such circumstances, there is another tool called C<h2xs>
that is able to translate an entire C header file into a corresponding
XS file that will provide glue to the functions/macros described in
the header file.

XS语言允许你描述C代码是如何使用的,以及对应的Perl代码是如何使用的 之间的映射关系。
它同样允许创建会被直接被翻译为C代码的Perl例程,即使它和已存在的C函数没有关系。
在C接口和Perl接口相似的场景下,XSUB声明和C函数的声明(K&R形式)基本一致。
在这样的场景下,有另一个工具C<h2xs>可以将整个C头文件翻译为对应的XS文件,
其将提供对应头文件中的描述的函数/宏的胶水代码。

The XS compiler is called B<xsubpp>.  This compiler creates
the constructs necessary to let an XSUB manipulate Perl values, and
creates the glue necessary to let Perl call the XSUB.  The compiler
uses B<typemaps> to determine how to map C function parameters
and output values to Perl values and back.  The default typemap
(which comes with Perl) handles many common C types.  A supplementary
typemap may also be needed to handle any special structures and types
for the library being linked. For more information on typemaps,
see L<perlxstypemap>.

XS 编译器被成为B<xsubpp>。这个编译器创建了必要的结构使得XSUB能够管理Perl的值,
并创建允许Perl调用XSUB的胶水代码。编译器使用B<typemaps>规定C函数参数和输出值是如何映射到Perl的值上的,反之亦然。
默认的typemap(Perl自带的)处理了很多普通C类型。一个补充的typemap被用于处理任何用于被链接的库的特殊的结构和类型。
请参见L<perlxstypemap>以获取更多信息。

A file in XS format starts with a C language section which goes until the
first C<MODULE =Z<>> directive.  Other XS directives and XSUB definitions
may follow this line.  The "language" used in this part of the file
is usually referred to as the XS language.  B<xsubpp> recognizes and
skips POD (see L<perlpod>) in both the C and XS language sections, which
allows the XS file to contain embedded documentation.

一个XS格式的文件以C语言段开头直到第一个C<MODULE = Z<>>条目。其余的XS条目和XSUB定义紧随这一行。
文件这部分使用的“语言”被称作XS语言。B<xsubpp>识别并跳过C和XS语言段的POD(参见L<perlpod>),
其允许XS文件包含嵌入的文档。

See L<perlxstut> for a tutorial on the whole extension creation process.

参见L<perlxstut>以查看完整创建拓展过程的入门指南。

Note: For some extensions, Dave Beazley's SWIG system may provide a
significantly more convenient mechanism for creating the extension
glue code.  See L<http://www.swig.org/> for more information.

注意:对于一些拓展而言,Dave Beazley的SWIG系统也许为创建拓展胶水代码提供了更方便的机制。
请看L<http://www.swig.org>以获得更多信息。

=head2 On The Road

=head2 开始进发

Many of the examples which follow will concentrate on creating an interface
between Perl and the ONC+ RPC bind library functions.  The rpcb_gettime()
function is used to demonstrate many features of the XS language.  This
function has two parameters; the first is an input parameter and the second
is an output parameter.  The function also returns a status value.

下面很多例子将集中在创建一个Perl和ONC+ RPC绑定库函数之间的接口上。
rpcb_gettime()函数被用于展示XS语言的很多特性。这个函数有两个参数;第一个是输入参数,
第二个为输出参数。函数同时返回一个状态码。

	bool_t rpcb_gettime(const char *host, time_t *timep);

From C this function will be called with the following
statements.

在C代码中这个函数将通过如下语句调用。

     #include <rpc/rpc.h>
     bool_t status;
     time_t timep;
     status = rpcb_gettime( "localhost", &timep );

If an XSUB is created to offer a direct translation between this function
and Perl, then this XSUB will be used from Perl with the following code.
The $status and $timep variables will contain the output of the function.

如果创建XSUB以提供这个函数和Perl之间的转换,Perl将会以一下方式使用XSUB。
$status和$timep变量将会包含函数的输出。

     use RPC;
     $status = rpcb_gettime( "localhost", $timep );

The following XS file shows an XS subroutine, or XSUB, which
demonstrates one possible interface to the rpcb_gettime()
function.  This XSUB represents a direct translation between
C and Perl and so preserves the interface even from Perl.
This XSUB will be invoked from Perl with the usage shown
above.  Note that the first three #include statements, for
C<EXTERN.h>, C<perl.h>, and C<XSUB.h>, will always be present at the
beginning of an XS file.  This approach and others will be
expanded later in this document.

以下XS文件内容是一个XS子例程,或者说XSUB,它展现了rpcb_gettime()的一种可能的接口。
XSUB带便C和Perl之间的直接转换,因此保留了接口。这个XSUN将会被Perl以如上所示的方式调用。
注意前三个#include语句,C<EXTERN.h>, C<perl.h>, 和 C<XSUB.h>,总是被放在XS文件的开头。
诸如此类的注意事项将在下文展开。

     #include "EXTERN.h"
     #include "perl.h"
     #include "XSUB.h"
     #include <rpc/rpc.h>

     MODULE = RPC  PACKAGE = RPC

     bool_t
     rpcb_gettime(host,timep)
          char *host
          time_t &timep
        OUTPUT:
          timep

Any extension to Perl, including those containing XSUBs,
should have a Perl module to serve as the bootstrap which
pulls the extension into Perl.  This module will export the
extension's functions and variables to the Perl program and
will cause the extension's XSUBs to be linked into Perl.
The following module will be used for most of the examples
in this document and should be used from Perl with the C<use>
command as shown earlier.  Perl modules are explained in
more detail later in this document.

Perl的任何拓展,包括那些包含有XSUBs的,都应该有一个Perl模块作为引导程序将拓展拉入Perl中。
这个模块应该向Perl程序导入拓展的函数和变量,将XSUB链接到Perl中。以下模块被用于本文中的大部分例子,
且应该在Perl中通过C<use>命令使用。本文的后续内容将更加深入地解释Perl模块。

     package RPC;

     require Exporter;
     require DynaLoader;
     @ISA = qw(Exporter DynaLoader);
     @EXPORT = qw( rpcb_gettime );

     bootstrap RPC;
     1;

Throughout this document a variety of interfaces to the rpcb_gettime()
XSUB will be explored.  The XSUBs will take their parameters in different
orders or will take different numbers of parameters.  In each case the
XSUB is an abstraction between Perl and the real C rpcb_gettime()
function, and the XSUB must always ensure that the real rpcb_gettime()
function is called with the correct parameters.  This abstraction will
allow the programmer to create a more Perl-like interface to the C
function.

贯穿整篇文档,一些列rpcb_gettime()的XSUB接口将被导出。XSUBs将会传入不同顺序,不同个数的参数。
在每种情况下XSUB是Perl和真实的C函数rpcb_gettime()之间的抽象层,XSUB必须保证真实的rpcb_gettime()函数是通过正确的参数调用的。
这个抽象层允许程序员创建更加具有Perl风格的对C的接口。

=head2 The Anatomy of an XSUB

=head2 XSUB 剖析

The simplest XSUBs consist of 3 parts: a description of the return
value, the name of the XSUB routine and the names of its arguments,
and a description of types or formats of the arguments.

最简单的XSUB包括三部分:一个返回值的描述,XSUB的名称以及其参数的名称,
和其参数类型或形式的描述。

The following XSUB allows a Perl program to access a C library function
called sin().  The XSUB will imitate the C function which takes a single
argument and returns a single value.

以下XSUB允许Perl程序访问一个名称为sin()的C库函数。XSUB将会模仿C函数只传递一个参数并返回一个值。

     double
     sin(x)
       double x

Optionally, one can merge the description of types and the list of
argument names, rewriting this as

另一种方案是合并类型和参数名称,重写如下:

     double
     sin(double x)

This makes this XSUB look similar to an ANSI C declaration.  An optional
semicolon is allowed after the argument list, as in

这使得XSUB看上去类似ANSI C的声明。参数列表后的分号是可选的,如:

     double
     sin(double x);

Parameters with C pointer types can have different semantic: C functions
with similar declarations

C指针类型的参数可以有不同的语义:C函数的类似声明:

     bool string_looks_as_a_number(char *s);
     bool make_char_uppercase(char *c);

are used in absolutely incompatible manner.  Parameters to these functions
could be described B<xsubpp> like this:

却有着完全不同的行为。这些函数的参数在B<xsubpp>中被描述为:

     char *  s
     char    &c

Both these XS declarations correspond to the C<char*> C type, but they have
different semantics, see L<"The & Unary Operator">.

这些XS声明都对应C类型C<char*>,但是它们有不同的语义,请参见L<"&一元操作符">。

It is convenient to think that the indirection operator
C<*> should be considered as a part of the type and the address operator C<&>
should be considered part of the variable.  See L<perlxstypemap>
for more info about handling qualifiers and unary operators in C types.

你可以很容易地想象间接操作符C<*>应该被认为是类型的一部分而地址操作副C<&>应该被认为是变量的一部分。
参看L<perlxstypemap>以获取更多关于处理C类型中修饰符与一元操作符的信息。

The function name and the return type must be placed on
separate lines and should be flush left-adjusted.

函数名称和返回类型必须位于不同的行而且应该左调整对齐。

  INCORRECT                        CORRECT

  double sin(x)                    double
    double x                       sin(x)
				     double x

The rest of the function description may be indented or left-adjusted. The
following example shows a function with its body left-adjusted.  Most
examples in this document will indent the body for better readability.

函数描述的剩下部分应该缩进或左调整对齐。以下例子显示了一个函数体左调整对齐的函数。
文档中的大多数例子将会缩进以更加易于阅读。

  CORRECT

  double
  sin(x)
  double x

More complicated XSUBs may contain many other sections.  Each section of
an XSUB starts with the corresponding keyword, such as INIT: or CLEANUP:.
However, the first two lines of an XSUB always contain the same data:
descriptions of the return type and the names of the function and its
parameters.  Whatever immediately follows these is considered to be
an INPUT: section unless explicitly marked with another keyword.
(See L<The INPUT: Keyword>.)

更加复杂的XSUBs也许会包含更多其他的节。XSUB的每一节都以相应的关键字开头,
比如INIT: 或 CLEANUP: 。然而,XSUB的前两行应该包含同样的数据:返回类型的描述和函数名称及其参数。
它们之后的被认为是一个INPUT: 节,除非显式地被标记为其他关键字。
(参考L<The INPUT: Keyword>。)

An XSUB section continues until another section-start keyword is found.

一个XSUB节会一直持续下去直到另一个 section-start关键字被发现。

=head2 The Argument Stack

=head2 参数栈

The Perl argument stack is used to store the values which are
sent as parameters to the XSUB and to store the XSUB's
return value(s).  In reality all Perl functions (including non-XSUB
ones) keep their values on this stack all the same time, each limited
to its own range of positions on the stack.  In this document the
first position on that stack which belongs to the active
function will be referred to as position 0 for that function.

Perl参数栈被用于存储作为参数发送给XSUB的值以及XSUB的返回值。
实际上所有的Perl函数(包括非XSUB的那些)都同时在这个栈上保存值,
每一个都限制在栈上自己被分配的位置范围中。
在本文档中当前活跃的函数的栈的第一个位置被函数作为位置0引用。

XSUBs refer to their stack arguments with the macro B<ST(x)>, where I<x>
refers to a position in this XSUB's part of the stack.  Position 0 for that
function would be known to the XSUB as ST(0).  The XSUB's incoming
parameters and outgoing return values always begin at ST(0).  For many
simple cases the B<xsubpp> compiler will generate the code necessary to
handle the argument stack by embedding code fragments found in the
typemaps.  In more complex cases the programmer must supply the code.

XSUBs通过宏B<ST(x)>引用到它们的栈参数,I<x>指向所属这个XSUB的栈的部分的位置。
函数的位置0通过ST(0)被XSUB获取到。XSUB的传入参数和传出的返回值总是从ST(0)开始。
在很多简单的场景下B<xsubpp>编译器将会生成必要的代码通过嵌入在typemaps中找到的代码块来处理参数栈。
更复杂的场景下程序员必须自己编写代码。

=head2 The RETVAL Variable

=head2 RETVAL 值

The RETVAL variable is a special C variable that is declared automatically
for you.  The C type of RETVAL matches the return type of the C library
function.  The B<xsubpp> compiler will declare this variable in each XSUB
with non-C<void> return type.  By default the generated C function
will use RETVAL to hold the return value of the C library function being
called.  In simple cases the value of RETVAL will be placed in ST(0) of
the argument stack where it can be received by Perl as the return value
of the XSUB.

RETVAL值是一个为你自动声明的特殊C值。RETVAL的C类型域C库函数返回类型是匹配的。
B<xsubpp>编译器将会为每一个非空返回类型的XSUB自动声明这个变量。
默认情况下生成的C函数将会使用RETVAL保存被调用的C库函数的返回值。
在简单的场景下RETVAL的值会被放到参数栈的ST(0),并被Perl作为XSUB的返回值接收到。

If the XSUB has a return type of C<void> then the compiler will
not declare a RETVAL variable for that function.  When using
a PPCODE: section no manipulation of the RETVAL variable is required, the
section may use direct stack manipulation to place output values on the stack.

如果XSUB有一个C<void>类型的返回值,那么编译器将不会为该函数声明RETVAL变量。
当使用PPCODE: 节时,不许要管理RETVAL变量,该节也许会直接管理栈以将输出值放到栈上。

If PPCODE: directive is not used, C<void> return value should be used
only for subroutines which do not return a value, I<even if> CODE:
directive is used which sets ST(0) explicitly.

如果没有使用PPCODE: 指令,C<void>返回值应该只有在不需要返回值的子例程中才使用,
即使使用了CODE: 指令(将会显式设置ST(0))。

Older versions of this document recommended to use C<void> return
value in such cases. It was discovered that this could lead to
segfaults in cases when XSUB was I<truly> C<void>. This practice is
now deprecated, and may be not supported at some future version. Use
the return value C<SV *> in such cases. (Currently C<xsubpp> contains
some heuristic code which tries to disambiguate between "truly-void"
and "old-practice-declared-as-void" functions. Hence your code is at
mercy of this heuristics unless you use C<SV *> as return value.)

这篇问单的早期版本建议在这个场景下使用C<void>返回值。
但是被发现在XSUB是真的void的场景下会导致段错误。这种用法现在被废弃了,而且在将来的版本中可能不再支持。
在这种场景下请使用C<SV *>返回值。
(当前C<xsubpp>包含一些启发式的代码用于区分"truely-void"和"old-practice-declared-as-void"函数。
因此你的代码只能依赖启发式算法的正确性了,除非你使用C<SV *>作为返回值)

=head2 Returning SVs, AVs and HVs through RETVAL

=head2 通过RETVAL返回SVs,AVs和HVs

When you're using RETVAL to return an C<SV *>, there's some magic
going on behind the scenes that should be mentioned. When you're
manipulating the argument stack using the ST(x) macro, for example,
you usually have to pay special attention to reference counts. (For
more about reference counts, see L<perlguts>.) To make your life
easier, the typemap file automatically makes C<RETVAL> mortal when
you're returning an C<SV *>. Thus, the following two XSUBs are more
or less equivalent:

当你使用RETVAL来返回一个C<SV *>时,其背后将会发生一下奇妙的事。
当你使用ST<x>宏管理参数栈的时候,比如,你通常需要注意引用计数。
(参见L<perlguts>以获取更多关于引用计数的信息。)为了让你的生活更加简单,
当你返回一个C<SV *>的时候,typemap文件自动将C<RETVAL>设为"将死的"。
因此,一下两个XSUB某种程度上是完全相同的:

  void
  alpha()
      PPCODE:
          ST(0) = newSVpv("Hello World",0);
          sv_2mortal(ST(0));
          XSRETURN(1);

  SV *
  beta()
      CODE:
          RETVAL = newSVpv("Hello World",0);
      OUTPUT:
          RETVAL

This is quite useful as it usually improves readability. While
this works fine for an C<SV *>, it's unfortunately not as easy
to have C<AV *> or C<HV *> as a return value. You I<should> be
able to write:

从增加可阅读性的角度来说这样非常有效。尽管对于C<SV *>来说这样能工作地很好,
但不幸的是对于C<AV *>和C<HV *>作为返回值而言没那么容易,你应该能够这样写:

  AV *
  array()
      CODE:
          RETVAL = newAV();
          /* do something with RETVAL */
      OUTPUT:
          RETVAL

But due to an unfixable bug (fixing it would break lots of existing
CPAN modules) in the typemap file, the reference count of the C<AV *>
is not properly decremented. Thus, the above XSUB would leak memory
whenever it is being called. The same problem exists for C<HV *>,
C<CV *>, and C<SVREF> (which indicates a scalar reference, not
a general C<SV *>).
In XS code on perls starting with perl 5.16, you can override the
typemaps for any of these types with a version that has proper
handling of refcounts. In your C<TYPEMAP> section, do

但是由于typemap文件中一些没有修复的bug(修复它们将导致大量已存在的CPAN模块失效),
C<AV *>的引用计数没有被减少。因此,以上XSUB会在调用时导致内存泄漏。
对C<HV *>,C<CV *>和C<SVREG>(表示一个scalar引用,不是一般的C<SV *>。)来说有同样的问题。
在从5.16版本开始的Perl XS代码中,你可以用能正确处理引用计数的版本覆盖typemaps中的任何类型。
在你的C<TYPEMAP>节中:

  AV*	T_AVREF_REFCOUNT_FIXED

to get the repaired variant. For backward compatibility with older
versions of perl, you can instead decrement the reference count
manually when you're returning one of the aforementioned
types using C<sv_2mortal>:

以获取修复后的变体。为了向后兼容老版本的perl,在返回之前提到的要使用C<sv_2mortal>的类型时你应该手动减少引用计数。

  AV *
  array()
      CODE:
          RETVAL = newAV();
          sv_2mortal((SV*)RETVAL);
          /* do something with RETVAL */
      OUTPUT:
          RETVAL

Remember that you don't have to do this for an C<SV *>. The reference
documentation for all core typemaps can be found in L<perlxstypemap>.

记住你不需要为C<SV *>做这个。所有核心typemaps的参考文档都可以在L<perlxstypemap>中看到。

=head2 The MODULE Keyword

=head2 模块关键字

The MODULE keyword is used to start the XS code and to specify the package
of the functions which are being defined.  All text preceding the first
MODULE keyword is considered C code and is passed through to the output with
POD stripped, but otherwise untouched.  Every XS module will have a
bootstrap function which is used to hook the XSUBs into Perl.  The package
name of this bootstrap function will match the value of the last MODULE
statement in the XS source files.  The value of MODULE should always remain
constant within the same XS file, though this is not required.

模块关键字被用于标识XS代码的开始以及说明定义的函数所属的模块。
所有在MODULE关键字之前的文本都本认为是C代码并在去除POD后输出。每一个XS模块都会有一个启动函数用于将XSUBs钩到Perl中。
启动函数的包名应该匹配XS源文件中最后一条MODULE语句,尽管着不是必须的。

The following example will start the XS code and will place
all functions in a package named RPC.

以下例子标识XS代码的开始并且会将所有函数放置到RPC包中。

     MODULE = RPC

=head2 The PACKAGE Keyword

=head2 PACKAGE 关键字

When functions within an XS source file must be separated into packages
the PACKAGE keyword should be used.  This keyword is used with the MODULE
keyword and must follow immediately after it when used.

当XS源文件中的函数必须要被分到不同包中时,应该使用PACKAGE关键字。
这个关键字和MODULE关键字一起使用,而且必须要立即跟在它后面。

     MODULE = RPC  PACKAGE = RPC

     [ XS code in package RPC ]

     MODULE = RPC  PACKAGE = RPCB

     [ XS code in package RPCB ]

     MODULE = RPC  PACKAGE = RPC

     [ XS code in package RPC ]

The same package name can be used more than once, allowing for
non-contiguous code. This is useful if you have a stronger ordering
principle than package names.

同一个包名可以被多次使用,以允许非连续代码。当你的排序原则和包名的顺序不一致的时候非常有用。

Although this keyword is optional and in some cases provides redundant
information it should always be used.  This keyword will ensure that the
XSUBs appear in the desired package.

尽管这个关键字是可选的而且在一些场景中提供的是多余的信息,它还是应该被使用。
它会保证XSUB会出现在期望的包中。

=head2 The PREFIX Keyword

=head2 PREFIX 关键字

The PREFIX keyword designates prefixes which should be
removed from the Perl function names.  If the C function is
C<rpcb_gettime()> and the PREFIX value is C<rpcb_> then Perl will
see this function as C<gettime()>.

PREFIX关键字

This keyword should follow the PACKAGE keyword when used.
If PACKAGE is not used then PREFIX should follow the MODULE
keyword.

这个关键字应该跟在PACKAGE关键字后面使用。如果PACKAGE没有使用那么PREFIX应该跟在MODULE关键字后面。

     MODULE = RPC  PREFIX = rpc_

     MODULE = RPC  PACKAGE = RPCB  PREFIX = rpcb_

=head2 The OUTPUT: Keyword

=head2 OUTPUT: 关键字

The OUTPUT: keyword indicates that certain function parameters should be
updated (new values made visible to Perl) when the XSUB terminates or that
certain values should be returned to the calling Perl function.  For
simple functions which have no CODE: or PPCODE: section,
such as the sin() function above, the RETVAL variable is
automatically designated as an output value.  For more complex functions
the B<xsubpp> compiler will need help to determine which variables are output
variables.

OUTPUT: 关键字表示某个函数的参数应该被更新(使得一些值对Perl可见)当其XSUB终止或某些值应该被返回到Perl函数的时候。
对于没有CODE: 段或PPCODE: 段的简单的函数,比如上面说的sin()函数,RETVAL变量自动被制定为返回值。
对于更复杂的函数B<xsubpp>编译器将需要额外的帮助以确定哪些变量是输出变量。

This keyword will normally be used to complement the CODE:  keyword.
The RETVAL variable is not recognized as an output variable when the
CODE: keyword is present.  The OUTPUT:  keyword is used in this
situation to tell the compiler that RETVAL really is an output
variable.

这个关键字通常会被用于作为CODE: 关键字的补充。当使用CODE: 关键字的时候RETVAL变量不会作为输出变量。
OUTPUT: 关键字被使用于这种场景以告诉编译器RETVAL是输出变量。

The OUTPUT: keyword can also be used to indicate that function parameters
are output variables.  This may be necessary when a parameter has been
modified within the function and the programmer would like the update to
be seen by Perl.

OUTPUT: 关键字可以被用于表示作为输出变量的函数参数。
当参数被在函数中被变更而且程序员希望Perl可以知道这次变更的时候需要这样做。

     bool_t
     rpcb_gettime(host,timep)
          char *host
          time_t &timep
        OUTPUT:
          timep

The OUTPUT: keyword will also allow an output parameter to
be mapped to a matching piece of code rather than to a
typemap.

OUTPUT: 关键字同样允许输出参数映射到匹配的代码快而不是typemap。

     bool_t
     rpcb_gettime(host,timep)
          char *host
          time_t &timep
        OUTPUT:
          timep sv_setnv(ST(1), (double)timep);

B<xsubpp> emits an automatic C<SvSETMAGIC()> for all parameters in the
OUTPUT section of the XSUB, except RETVAL.  This is the usually desired
behavior, as it takes care of properly invoking 'set' magic on output
parameters (needed for hash or array element parameters that must be
created if they didn't exist).  If for some reason, this behavior is
not desired, the OUTPUT section may contain a C<SETMAGIC: DISABLE> line
to disable it for the remainder of the parameters in the OUTPUT section.
Likewise,  C<SETMAGIC: ENABLE> can be used to reenable it for the
remainder of the OUTPUT section.  See L<perlguts> for more details
about 'set' magic.

B<xsubpp> 会为XSUB的OUTPUT节中所有参数(除了RETVAL)出发一次自动的C<SvSETMAGIC()>。
这通常是期望的行为,它会对传出参数恰当地出发'set'魔法(哈稀表和数组成员参数需要这样,当它们不存在的时候必须要创建)。
如果因为某种原因不需要这种行为,OUTPUT节应该包含一行C<SETMAGIC: DISABLE>以对剩余的参数关闭这个特性。
相反,C<SETMAGIC: ENABLE>用于为剩余的参数打开该特性。参见L<perlguts>以获得更多信息。

B<xsubpp>

=head2 The NO_OUTPUT Keyword

=head2 NO_OUTPUT 关键字

The NO_OUTPUT can be placed as the first token of the XSUB.  This keyword
indicates that while the C subroutine we provide an interface to has
a non-C<void> return type, the return value of this C subroutine should not
be returned from the generated Perl subroutine.

NO_OUTPUT可以作为XSUB的第一个词。这个关键字标识尽管我们为之提供接口的C子例程有一个非空的返回类型,
这个C子例程的返回值不应该从生成的Perl子例程返回。

With this keyword present L<The RETVAL Variable> is created, and in the
generated call to the subroutine this variable is assigned to, but the value
of this variable is not going to be used in the auto-generated code.

有这个关键字以后L<RETVAL变量>还是会被创建,而且在这个子例程生成的代码中这个变量还被赋值了,
但是这个值不会被自动生成的代码使用。

This keyword makes sense only if C<RETVAL> is going to be accessed by the
user-supplied code.  It is especially useful to make a function interface
more Perl-like, especially when the C return value is just an error condition
indicator.  For example,

这个关键字只有在C<RETVAL>将被用户提供的代码使用的时候才有意义。
尤其是为了将一个函数接口变得更有Perl风格,或者当C返回值只是一个错误条件的标记。
例如:

  NO_OUTPUT int
  delete_file(char *name)
    POSTCALL:
      if (RETVAL != 0)
	  croak("Error %d while deleting file '%s'", RETVAL, name);

Here the generated XS function returns nothing on success, and will die()
with a meaningful error message on error.

这里生成的XS函数在成功时什么都不会返回,在失败时会die()并对error流输出有意以的错误信息。

=head2 The CODE: Keyword

=head2 CODE: 关键字

This keyword is used in more complicated XSUBs which require
special handling for the C function.  The RETVAL variable is
still declared, but it will not be returned unless it is specified
in the OUTPUT: section.

这个关键字被用于需要对C函数做特殊处理的更加复杂的XSUB。
RETVAL变量仍然被声明,但是它不会被返回,除非在OUTPUT: 节中被明确指明。

The following XSUB is for a C function which requires special handling of
its parameters.  The Perl usage is given first.

一下XSUB对应的C函数需要对其参数做特殊处理。Perl的用法先给出:

     $status = rpcb_gettime( "localhost", $timep );

The XSUB follows.

XSUB如下:

     bool_t
     rpcb_gettime(host,timep)
          char *host
          time_t timep
        CODE:
               RETVAL = rpcb_gettime( host, &timep );
        OUTPUT:
          timep
          RETVAL

=head2 The INIT: Keyword

=head2 INIT: 关键字

The INIT: keyword allows initialization to be inserted into the XSUB before
the compiler generates the call to the C function.  Unlike the CODE: keyword
above, this keyword does not affect the way the compiler handles RETVAL.

INIT: 关键字允许在编译前生成调用C函数的代码之前将初始化插入到XSUB中。
与CODE: 关键字不同的是,这个关键字并不影响编译器处理RETVAL的方式。

    bool_t
    rpcb_gettime(host,timep)
          char *host
          time_t &timep
	INIT:
	  printf("# Host is %s\n", host );
        OUTPUT:
          timep

Another use for the INIT: section is to check for preconditions before
making a call to the C function:

另一个INIT的用途是:在调用C函数之前检查预置条件:

    long long
    lldiv(a,b)
	long long a
	long long b
      INIT:
	if (a == 0 && b == 0)
	    XSRETURN_UNDEF;
	if (b == 0)
	    croak("lldiv: cannot divide by 0");

=head2 The NO_INIT Keyword

=head2 NO_INIT 关键字

The NO_INIT keyword is used to indicate that a function
parameter is being used only as an output value.  The B<xsubpp>
compiler will normally generate code to read the values of
all function parameters from the argument stack and assign
them to C variables upon entry to the function.  NO_INIT
will tell the compiler that some parameters will be used for
output rather than for input and that they will be handled
before the function terminates.

NO_INIT关键字被用于表示一个函数参数只被用于输出值。
B<xsubpp>编译器通常会生成代码从参数栈中读取所有的函数参数,
并将它们赋予函数入口处的C变量。NO_INIT将会告诉编译器一些参数是被用于输出值的,
而不是输入,它们将在函数终止前被处理。

The following example shows a variation of the rpcb_gettime() function.
This function uses the timep variable only as an output variable and does
not care about its initial contents.

一下例子展示了一个rpcb_gettime()函数的变体。这个函数使用timp变量仅作为输出变量而
不会在意它的初始内容。

     bool_t
     rpcb_gettime(host,timep)
          char *host
          time_t &timep = NO_INIT
        OUTPUT:
          timep

=head2 The TYPEMAP: Keyword

=head2 TYPEMAP: 关键字

Starting with Perl 5.16, you can embed typemaps into your XS code
instead of or in addition to typemaps in a separate file.  Multiple
such embedded typemaps will be processed in order of appearance in
the XS code and like local typemap files take precendence over the
default typemap, the embedded typemaps may overwrite previous
definitions of TYPEMAP, INPUT, and OUTPUT stanzas.  The syntax for
embedded typemaps is

从Perl 5.16开始,你可以向你的XS嵌入typemaps而不必向另外的文件添加typemaps了。
多个这样嵌入的typemaps将被顺序处理,就像本地的typemap文件一样覆盖默认的typemap,
嵌入的typemap也许会覆盖之前的TYPEMAP,INPUT和OUTPUT节 定义。
嵌入typemaps的语法为:

      TYPEMAP: <<HERE
      ... your typemap code here ...
      HERE

where the C<TYPEMAP> keyword must appear in the first column of a
new line.

C<TYPEMAP>关键字必须要在新的一行的第一列出现。

Refer to L<perlxstypemap> for details on writing typemaps.

参见L<perlxstypemap>以获取更多如何书写typemaps的信息。

=head2 Initializing Function Parameters

=head2 初始化函数参数

C function parameters are normally initialized with their values from
the argument stack (which in turn contains the parameters that were
passed to the XSUB from Perl).  The typemaps contain the
code segments which are used to translate the Perl values to
the C parameters.  The programmer, however, is allowed to
override the typemaps and supply alternate (or additional)
initialization code.  Initialization code starts with the first
C<=>, C<;> or C<+> on a line in the INPUT: section.  The only
exception happens if this C<;> terminates the line, then this C<;>
is quietly ignored.

C函数参数通常是通过参数栈上的值来初始化它们的值的(也就是说包含了我们从Perl传入XSUB的参数)。
typemaps包含了用于将Perl值转为C参数的代码块。
程序员可以覆盖这些typemaps并提供另外的(或添加)初始化代码
初始化代码以INPUT: 节中一行中的第一个C<=>,C<;>或C<+>开始。
唯一的例外是:如果这个C<;>终止了这一行,那么这个C<;>会被忽略。

The following code demonstrates how to supply initialization code for
function parameters.  The initialization code is eval'ed within double
quotes by the compiler before it is added to the output so anything
which should be interpreted literally [mainly C<$>, C<@>, or C<\\>]
must be protected with backslashes.  The variables C<$var>, C<$arg>,
and C<$type> can be used as in typemaps.

以下代码展示了如何为函数参数提供初始化代码。初始化代码在被添加到输出之前会被编译器包裹在双引号中
进行eval,因此任何应该按文本含义解释的部分【主要是C<$>,C<@>或C<\\>】都必须用反斜杠保护起来。
变量C<$var>,C<$arg>和C<$type>如在typemaps中一样可以使用。

     bool_t
     rpcb_gettime(host,timep)
          char *host = (char *)SvPV_nolen($arg);
          time_t &timep = 0;
        OUTPUT:
          timep

This should not be used to supply default values for parameters.  One
would normally use this when a function parameter must be processed by
another library function before it can be used.  Default parameters are
covered in the next section.

这不应该用于向参数提供默认值。一般在当一个函数参数使用前必须要被另一个库函数处理的时候才使用它。
默认参数会在下一节说明。

If the initialization begins with C<=>, then it is output in
the declaration for the input variable, replacing the initialization
supplied by the typemap.  If the initialization
begins with C<;> or C<+>, then it is performed after
all of the input variables have been declared.  In the C<;>
case the initialization normally supplied by the typemap is not performed.
For the C<+> case, the declaration for the variable will include the
initialization from the typemap.  A global
variable, C<%v>, is available for the truly rare case where
information from one initialization is needed in another
initialization.

如果初始化代码以C<=>开头,那么它将输出得到输入变量的声明之中,代替typemap提供的初始化代码。
如果初始化以C<;>或C<+>开头,那么它将在所有输入变量声明之后执行。
在C<;>的情况下由typemap提供的代码将不会执行。
在C<+>的情况下变量的声明将会包含typemap提供的初始化代码。
全局变量C<%v>在少数需要在不同初始化过程中共享数据的场景中可以使用。

Here's a truly obscure example:

这是一个粗略的例子:

     bool_t
     rpcb_gettime(host,timep)
          time_t &timep; /* \$v{timep}=@{[$v{timep}=$arg]} */
          char *host + SvOK($v{timep}) ? SvPV_nolen($arg) : NULL;
        OUTPUT:
          timep

The construct C<\$v{timep}=@{[$v{timep}=$arg]}> used in the above
example has a two-fold purpose: first, when this line is processed by
B<xsubpp>, the Perl snippet C<$v{timep}=$arg> is evaluated.  Second,
the text of the evaluated snippet is output into the generated C file
(inside a C comment)!  During the processing of C<char *host> line,
C<$arg> will evaluate to C<ST(0)>, and C<$v{timep}> will evaluate to
C<ST(1)>.

上面提到的C<\$v{timep}=@{[$v{timep}=$arg]}>结构有两层含义:首先,
当这一行被B<xsubpp>处理时,Perl代码片段C<$v{timep}=$arg>被求值。
其次,求值得出的结果被输出到生成的C文件中(在C注释中)!在处理C<char *host>行时,
C<$arg>将被计算并保存到C<ST(0)>,C<$v{timep}>将被计算算并保存到C<ST{1}>。

=head2 Default Parameter Values

=head2 默认参数值

Default values for XSUB arguments can be specified by placing an
assignment statement in the parameter list.  The default value may
be a number, a string or the special string C<NO_INIT>.  Defaults should
always be used on the right-most parameters only.

XSUB参数的默认值可以通过在参数列表中放置一条赋值语句实现。
默认值也许是一个数字,一个字符串或一个特殊字符串C<NO_INIT>。
默认值应当总是被用在括号的最右边。

To allow the XSUB for rpcb_gettime() to have a default host
value the parameters to the XSUB could be rearranged.  The
XSUB will then call the real rpcb_gettime() function with
the parameters in the correct order.  This XSUB can be called
from Perl with either of the following statements:

为了使得rpcb_gettime()的XSUB有一个默认值,XSUB的参数应该是可重置的。
XSUB将会接着以正确的参数顺序调用真正的rpcb_gettime()函数。
这个XSUB可以从Perl中按以下任意一种方式调用。

     $status = rpcb_gettime( $timep, $host );

     $status = rpcb_gettime( $timep );

The XSUB will look like the code  which  follows.   A  CODE:
block  is used to call the real rpcb_gettime() function with
the parameters in the correct order for that function.

XSUB看起来向下面的代码。一个CODE: 块被用于按正确的参数顺序调用真实的recb_gettime()函数。

     bool_t
     rpcb_gettime(timep,host="localhost")
          char *host
          time_t timep = NO_INIT
        CODE:
               RETVAL = rpcb_gettime( host, &timep );
        OUTPUT:
          timep
          RETVAL

=head2 The PREINIT: Keyword

=head2 PREINIT: 关键字

The PREINIT: keyword allows extra variables to be declared immediately
before or after the declarations of the parameters from the INPUT: section
are emitted.

PREINIT: 关键字允许额外的变量在INPUT: 节的参数声明之前会之后立即声明。

If a variable is declared inside a CODE: section it will follow any typemap
code that is emitted for the input parameters.  This may result in the
declaration ending up after C code, which is C syntax error.  Similar
errors may happen with an explicit C<;>-type or C<+>-type initialization of
parameters is used (see L<"Initializing Function Parameters">).  Declaring
these variables in an INIT: section will not help.

如果一个变量在CODE: 节中声明,它将会跟在任何由输入参数生成的typemap代码之后。
这也许会导致这个声明在C代码结束后才声明,造成一个C语法错误。
当显式地使用<;>类型或<+>类型的参数初始化方式时(参见L<"初始化函数参数">)也会发生类似的错误。
在INIT: 节声明这些变量也不会有什么帮助。

In such cases, to force an additional variable to be declared together
with declarations of other variables, place the declaration into a
PREINIT: section.  The PREINIT: keyword may be used one or more times
within an XSUB.

在这样的场景中,为了强制一个额外的变量与其他变量一起被声明,需要将声明放置到PREINIT: 节。
PREINIT: 关键字可能在一个XSUB中会被使用多次。

The following examples are equivalent, but if the code is using complex
typemaps then the first example is safer.

以下代码是等效的,但是如果代码使用复杂的typemaps,则第一个例子更加安全。

     bool_t
     rpcb_gettime(timep)
          time_t timep = NO_INIT
	PREINIT:
          char *host = "localhost";
        CODE:
	  RETVAL = rpcb_gettime( host, &timep );
        OUTPUT:
          timep
          RETVAL

For this particular case an INIT: keyword would generate the
same C code as the PREINIT: keyword.  Another correct, but error-prone example:

这个特殊的例子中INIT: 关键字和PREINIT: 关键字会生成一样的C代码。
另一个正确但易出错的例子是:

     bool_t
     rpcb_gettime(timep)
          time_t timep = NO_INIT
	CODE:
          char *host = "localhost";
	  RETVAL = rpcb_gettime( host, &timep );
        OUTPUT:
          timep
          RETVAL

Another way to declare C<host> is to use a C block in the CODE: section:

另一种声明C<host>的方法是在CODE: 节中使用一个C代码块:

     bool_t
     rpcb_gettime(timep)
          time_t timep = NO_INIT
	CODE:
	  {
            char *host = "localhost";
	    RETVAL = rpcb_gettime( host, &timep );
	  }
        OUTPUT:
          timep
          RETVAL

The ability to put additional declarations before the typemap entries are
processed is very handy in the cases when typemap conversions manipulate
some global state:

将额外的变量声明放在typemap条目之前的能力在typemap转换管理西写全局状态的时候非常有用:

    MyObject
    mutate(o)
	PREINIT:
	    MyState st = global_state;
	INPUT:
	    MyObject o;
	CLEANUP:
	    reset_to(global_state, st);

Here we suppose that conversion to C<MyObject> in the INPUT: section and from
MyObject when processing RETVAL will modify a global variable C<global_state>.
After these conversions are performed, we restore the old value of
C<global_state> (to avoid memory leaks, for example).

这里我们假设INPUT: 节中到C<MyObject>的转换,
以及处理RETVAL时从MyObject的转换会改变全局变量C<global_state>。
在这些转换完成后,我们将C<global_state>原来的值恢复(比如为了避免内存泄漏)。

There is another way to trade clarity for compactness: INPUT sections allow
declaration of C variables which do not appear in the parameter list of
a subroutine.  Thus the above code for mutate() can be rewritten as

还有另一种牺牲清晰性以获得严密性的例子:INPUT节允许声明没有出现在参数列表中的C变量。
因此以上mutate()的代码可以被重写为:

    MyObject
    mutate(o)
	  MyState st = global_state;
	  MyObject o;
	CLEANUP:
	  reset_to(global_state, st);

and the code for rpcb_gettime() can be rewritten as

而rpcb_gettime()的代码可以被重写为:

     bool_t
     rpcb_gettime(timep)
	  time_t timep = NO_INIT
	  char *host = "localhost";
	C_ARGS:
	  host, &timep
	OUTPUT:
          timep
          RETVAL

=head2 The SCOPE: Keyword

=head2 SCOPE: 关键字

The SCOPE: keyword allows scoping to be enabled for a particular XSUB. If
enabled, the XSUB will invoke ENTER and LEAVE automatically.

SCOPE: 关键字使得在某个XSUB中允许出现作用域。如果被允许,这个XSUB将会自动触发ENTER和LEAVE。

To support potentially complex type mappings, if a typemap entry used
by an XSUB contains a comment like C</*scope*/> then scoping will
be automatically enabled for that XSUB.

为了支持潜在的复杂类型映射,如果一个XSUB是中使用的typemap条目包含一个像C</*scoope*/>的注释,
那么这个scoping将被对于这个XSUB自动允许。

To enable scoping:

为了打开scoping:

    SCOPE: ENABLE

To disable scoping:

为了关闭scoping:

    SCOPE: DISABLE

=head2 The INPUT: Keyword

=head2 INPUT: 关键字

The XSUB's parameters are usually evaluated immediately after entering the
XSUB.  The INPUT: keyword can be used to force those parameters to be
evaluated a little later.  The INPUT: keyword can be used multiple times
within an XSUB and can be used to list one or more input variables.  This
keyword is used with the PREINIT: keyword.

XSUB的参数通常在进入XSUB后立即被计算出来。INPUT: 关键字可以被用于强制这些参数被延迟计算。
INPUT: 关键字能被在XSUB中多处使用,而且能被用于列出多个输入参数。
这个关键字被和PREINIT: 关键字一起使用。

The following example shows how the input parameter C<timep> can be
evaluated late, after a PREINIT.

以下代码展示了输入参数C<timpe>是如何在延迟到PREINIT之后被计算的。

    bool_t
    rpcb_gettime(host,timep)
          char *host
	PREINIT:
	  time_t tt;
	INPUT:
          time_t timep
        CODE:
               RETVAL = rpcb_gettime( host, &tt );
	       timep = tt;
        OUTPUT:
          timep
          RETVAL

The next example shows each input parameter evaluated late.

下一个例子展示了每一个输入参数都被延迟计算。

    bool_t
    rpcb_gettime(host,timep)
	PREINIT:
	  time_t tt;
	INPUT:
          char *host
	PREINIT:
	  char *h;
	INPUT:
          time_t timep
        CODE:
	       h = host;
	       RETVAL = rpcb_gettime( h, &tt );
	       timep = tt;
        OUTPUT:
          timep
          RETVAL

Since INPUT sections allow declaration of C variables which do not appear
in the parameter list of a subroutine, this may be shortened to:

由于允许在INPUT节中声明没有出现在子例程参数列表中的C变量,这可以被简写为:

    bool_t
    rpcb_gettime(host,timep)
	  time_t tt;
          char *host;
	  char *h = host;
          time_t timep;
        CODE:
	  RETVAL = rpcb_gettime( h, &tt );
	  timep = tt;
        OUTPUT:
          timep
          RETVAL

(We used our knowledge that input conversion for C<char *> is a "simple" one,
thus C<host> is initialized on the declaration line, and our assignment
C<h = host> is not performed too early.  Otherwise one would need to have the
assignment C<h = host> in a CODE: or INIT: section.)

(我们已知C<char*>的输入转换是"简单"的类型,因此C<host>在声明的哪一行就初始化了,
于是C<h = host>并没有执行得太早。否则需要将C<h = host>赋值语句放在CODE: 或INIT: 段。)

=head2 The IN/OUTLIST/IN_OUTLIST/OUT/IN_OUT Keywords

=head2 IN/OUTLIST/IN_OUTLIST/OUT/IN_OUT 关键字

In the list of parameters for an XSUB, one can precede parameter names
by the C<IN>/C<OUTLIST>/C<IN_OUTLIST>/C<OUT>/C<IN_OUT> keywords.
C<IN> keyword is the default, the other keywords indicate how the Perl
interface should differ from the C interface.

在XSUB的参数列表中,可以在参数名称前添加C<IN>/C<OUTLIST>/C<IN_OUTLIST>/C<OUT>/C<IN_OUT>关键字。
C<IN>关键字是默认设置的,其他关键字标识Perl接口和C接口的区别。

Parameters preceded by C<OUTLIST>/C<IN_OUTLIST>/C<OUT>/C<IN_OUT>
keywords are considered to be used by the C subroutine I<via
pointers>.  C<OUTLIST>/C<OUT> keywords indicate that the C subroutine
does not inspect the memory pointed by this parameter, but will write
through this pointer to provide additional return values.

以C<OUTLIST>/C<IN_OUTLIST>/C<OUT>/C<IN_OUT>开头的参数被认为是通过指针被C子例程访问的。
C<OUTLIST>/C<OUT>关键字表示C子例程不会查看参数指向的内存内容,但是会通过指针写入以传输额外的返回值。

Parameters preceded by C<OUTLIST> keyword do not appear in the usage
signature of the generated Perl function.

以C<OUTLIST>关键字开头的参数不会出现在生成的Perl函数的使用签名中。

Parameters preceded by C<IN_OUTLIST>/C<IN_OUT>/C<OUT> I<do> appear as
parameters to the Perl function.  With the exception of
C<OUT>-parameters, these parameters are converted to the corresponding
C type, then pointers to these data are given as arguments to the C
function.  It is expected that the C function will write through these
pointers.

以C<IN_OUTLIST>/C<IN_OUT>/C<OUT>开头的参数的确会作为Perl函数的参数出现。
除了C<OUT>参数外,这些参数都会被转为对应的C类型,然后这些数据的指针作为参数传给C函数,
并期望C函数会向这些指针写入。

The return list of the generated Perl function consists of the C return value
from the function (unless the XSUB is of C<void> return type or
C<The NO_OUTPUT Keyword> was used) followed by all the C<OUTLIST>
and C<IN_OUTLIST> parameters (in the order of appearance).  On the
return from the XSUB the C<IN_OUT>/C<OUT> Perl parameter will be
modified to have the values written by the C function.

生成的Perl函数的返回列表包含了C函数的返回值
(除非XSUB是C<oid>返回类型或使用了C<NO_OUTPUT关键字>)
以及所有C<OUTLIST>和C<IN_OUTLIST>参数(按照出现的顺序排序)。
当从XSUB返回时C<IN_OUT>/C<OUT>Perl参数会被改变为C函数写入的值。

For example, an XSUB

例如,XSUB

  void
  day_month(OUTLIST day, IN unix_time, OUTLIST month)
    int day
    int unix_time
    int month

should be used from Perl as

在Perl中应该这样调用:

  my ($day, $month) = day_month(time);

The C signature of the corresponding function should be

对应的C函数签名为:

  void day_month(int *day, int unix_time, int *month);

The C<IN>/C<OUTLIST>/C<IN_OUTLIST>/C<IN_OUT>/C<OUT> keywords can be
mixed with ANSI-style declarations, as in

C<IN>/C<OUTLIST>/C<IN_OUTLIST>/C<IN_OUT>/C<OUT>关键字可以与ANSI风格的声明混合使用,
比如:

  void
  day_month(OUTLIST int day, int unix_time, OUTLIST int month)

(here the optional C<IN> keyword is omitted).

(这里可选的C<IN>关键字被忽略了)。

The C<IN_OUT> parameters are identical with parameters introduced with
L<The & Unary Operator> and put into the C<OUTPUT:> section (see
L<The OUTPUT: Keyword>).  The C<IN_OUTLIST> parameters are very similar,
the only difference being that the value C function writes through the
pointer would not modify the Perl parameter, but is put in the output
list.

C<IN_OUT>参数是和L<&一元操作符>引入并将其放入C<OUTPUT:>段的参数是一样的
(参见L<OUTPUT: 关键字>一节)。C<IN_OUTPUT>参数与之非常类似,
唯一的不同是C函数写入的值不会修改Perl参数,但是会从返回列表返回。

The C<OUTLIST>/C<OUT> parameter differ from C<IN_OUTLIST>/C<IN_OUT>
parameters only by the initial value of the Perl parameter not
being read (and not being given to the C function - which gets some
garbage instead).  For example, the same C function as above can be
interfaced with as

C<OUTLIST>/C<OUT>参数与C<IN_OUTLIST>/C<IN_OUT>参数的区别在于Perl参数的初始值不会被读取
(也就不会被给予C函数 - 它得到的只是一些无意义的内容)。例如,和上面同样的C函数可以被定义成这样的接口:

  void day_month(OUT int day, int unix_time, OUT int month);

or

或者

  void
  day_month(day, unix_time, month)
      int &day = NO_INIT
      int  unix_time
      int &month = NO_INIT
    OUTPUT:
      day
      month

However, the generated Perl function is called in very C-ish style:

然而,生成的Perl函数以一种非常C风格的方式调用:

  my ($day, $month);
  day_month($day, time, $month);

=head2 The C<length(NAME)> Keyword

=head2 C<length(NAME)> 关键字

If one of the input arguments to the C function is the length of a string
argument C<NAME>, one can substitute the name of the length-argument by
C<length(NAME)> in the XSUB declaration.  This argument must be omitted when
the generated Perl function is called.  E.g.,

如果C函数的一个输入参数是一个字符串参数C<NAME>的长度,那么可以用C<length(NAME)>替代长度参数的名字。
当调用生成的Perl函数时这个参数必须要被省略。

  void
  dump_chars(char *s, short l)
  {
    short n = 0;
    while (n < l) {
        printf("s[%d] = \"\\%#03o\"\n", n, (int)s[n]);
        n++;
    }
  }

  MODULE = x		PACKAGE = x

  void dump_chars(char *s, short length(s))

should be called as C<dump_chars($string)>.

应该这样调用 C<dump_chars($string)>。

This directive is supported with ANSI-type function declarations only.

这个条目只支持ANSI类型的函数声明。

=head2 Variable-length Parameter Lists

=head2 变长参数列表

XSUBs can have variable-length parameter lists by specifying an ellipsis
C<(...)> in the parameter list.  This use of the ellipsis is similar to that
found in ANSI C.  The programmer is able to determine the number of
arguments passed to the XSUB by examining the C<items> variable which the
B<xsubpp> compiler supplies for all XSUBs.  By using this mechanism one can
create an XSUB which accepts a list of parameters of unknown length.

XSUB可以通过在参数列表中添加一个省略号C<...>以实现变长参数列表。
省略号的用法和ANSI C中的类似。程序员可以通过检查C<items>变量获取传给XSUB的参数个数,
B<xsubpp>编译器会为所有的XSUB提供C<items>变量。通过使用这个机制,
可以创建一个接收未知长度参数列表的XSUB。

The I<host> parameter for the rpcb_gettime() XSUB can be
optional so the ellipsis can be used to indicate that the
XSUB will take a variable number of parameters.  Perl should
be able to call this XSUB with either of the following statements.

rpcb_gettime() XSUB的I<host>变量是可选的,这样省略号可以被用于表明XSUB会接收变长数量的参数。
Perl应该可以以以下方式调用XSUB。

     $status = rpcb_gettime( $timep, $host );

     $status = rpcb_gettime( $timep );

The XS code, with ellipsis, follows.

带有省略号的XS代码如下:

     bool_t
     rpcb_gettime(timep, ...)
          time_t timep = NO_INIT
	PREINIT:
          char *host = "localhost";
        CODE:
	  if( items > 1 )
	       host = (char *)SvPV_nolen(ST(1));
	  RETVAL = rpcb_gettime( host, &timep );
        OUTPUT:
          timep
          RETVAL

=head2 The C_ARGS: Keyword

=head2 C_ARGS: 关键字

The C_ARGS: keyword allows creating of XSUBS which have different
calling sequence from Perl than from C, without a need to write
CODE: or PPCODE: section.  The contents of the C_ARGS: paragraph is
put as the argument to the called C function without any change.

C_ARGS: 关键字允许创建那种从Perl和从C中有着不同调用顺序的XSUB,而不许要写CODE: 或 PPCODE: 段。
C_ARGS: 段的内容作为被调用的C函数的参数,不做任何变换。

For example, suppose that a C function is declared as

例如,一个C函数被声明为:

    symbolic nth_derivative(int n, symbolic function, int flags);

and that the default flags are kept in a global C variable
C<default_flags>.  Suppose that you want to create an interface which
is called as

而且默认标志被保存在C全局变量C<default_flags>中。假如你像创建一个这样调用的接口:

    $second_deriv = $function->nth_derivative(2);

To do this, declare the XSUB as

为了实现这个,这样声明XSUB

    symbolic
    nth_derivative(function, n)
	symbolic	function
	int		n
      C_ARGS:
	n, function, default_flags

=head2 The PPCODE: Keyword

=head2 PPCODE: 关键字

The PPCODE: keyword is an alternate form of the CODE: keyword and is used
to tell the B<xsubpp> compiler that the programmer is supplying the code to
control the argument stack for the XSUBs return values.  Occasionally one
will want an XSUB to return a list of values rather than a single value.
In these cases one must use PPCODE: and then explicitly push the list of
values on the stack.  The PPCODE: and CODE:  keywords should not be used
together within the same XSUB.

PPCODE: 关键字是CODE: 关键字的另一种形式,
被用于告诉B<xsubpp>编译器程序员会提供管理XSUB的返回值的参数栈的代码。
有时候我们期望XSUB返回一个列表的值而不是单个值。
在这些场景下必须要使用PPCODE: 并且显式得将列表值推到栈上。
PPCODE: 和CODE: 关键字不应该被用在同一个XSUB中。

The actual difference between PPCODE: and CODE: sections is in the
initialization of C<SP> macro (which stands for the I<current> Perl
stack pointer), and in the handling of data on the stack when returning
from an XSUB.  In CODE: sections SP preserves the value which was on
entry to the XSUB: SP is on the function pointer (which follows the
last parameter).  In PPCODE: sections SP is moved backward to the
beginning of the parameter list, which allows C<PUSH*()> macros
to place output values in the place Perl expects them to be when
the XSUB returns back to Perl.

PPCODE: 和 CODE: 节实际上的不同在于C<SP>宏的初始化(代表当前Perl栈指针)以及当从XSUB返回时
栈中数据的处理方式。在CODE: 节,SP保留了进入XSUB时的值:SP在函数指针上(跟着最后一个参数)。
在PPCODE: 节,SP被移动到参数列表的开头,这样就允许C<PUSH*()>宏XSUB返回到Perl的时候将输出值放到
Perl期望它们所在的位置。

The generated trailer for a CODE: section ensures that the number of return
values Perl will see is either 0 or 1 (depending on the C<void>ness of the
return value of the C function, and heuristics mentioned in
L<"The RETVAL Variable">).  The trailer generated for a PPCODE: section
is based on the number of return values and on the number of times
C<SP> was updated by C<[X]PUSH*()> macros.

CODE: 节生成的尾部保证了Perl可以看到的返回值不是0个就是1个(取决于C函数返回值是否为C<void>
,以及在L<"RETVAL变量">)中提到的启发式算法。PPCODE: 节生成的尾部取决于返回值的数量以及
C<SP>被用C<[XPUSH*()>宏作用的次数。

Note that macros C<ST(i)>, C<XST_m*()> and C<XSRETURN*()> work equally
well in CODE: sections and PPCODE: sections.

注意宏C<ST(i)>, C<XST_m*()> 和 C<XSRETURN*()>在CODE: 节和PPCODE: 节中同样可以工作。

The following XSUB will call the C rpcb_gettime() function
and will return its two output values, timep and status, to
Perl as a single list.

以下XSUB将会调用rpcb_gettime()函数,并将其两个输出值返回,timep和status,对于Perl来说就是一个列表。

     void
     rpcb_gettime(host)
          char *host
	PREINIT:
          time_t  timep;
          bool_t  status;
        PPCODE:
          status = rpcb_gettime( host, &timep );
          EXTEND(SP, 2);
          PUSHs(sv_2mortal(newSViv(status)));
          PUSHs(sv_2mortal(newSViv(timep)));

Notice that the programmer must supply the C code necessary
to have the real rpcb_gettime() function called and to have
the return values properly placed on the argument stack.

注意到程序员必须提供C代码以调用rpcb_gettime(0函数,并将返回值放置到参数栈上。

The C<void> return type for this function tells the B<xsubpp> compiler that
the RETVAL variable is not needed or used and that it should not be created.
In most scenarios the void return type should be used with the PPCODE:
directive.

这个函数的C<void>返回类型会告诉B<xsubpp>编译器不许要RETVAL变量,因此不用创建。
在大多数场景下void返回类型应该与PPCODE: 条目一起使用。

The EXTEND() macro is used to make room on the argument
stack for 2 return values.  The PPCODE: directive causes the
B<xsubpp> compiler to create a stack pointer available as C<SP>, and it
is this pointer which is being used in the EXTEND() macro.
The values are then pushed onto the stack with the PUSHs()
macro.

EXTEND()宏被用于为两个返回参数提供参数栈空间。PPCODE: 条目导致B<xsubpp>编译器创建一个
可被C<SP>访问的栈指针,这个指针可以被EXTEND()宏使用。
然后再通过PUSHs()宏将值压栈。

Now the rpcb_gettime() function can be used from Perl with
the following statement.

现在rpcb_gettime()函数被Perl按以下方式调用:

     ($status, $timep) = rpcb_gettime("localhost");

When handling output parameters with a PPCODE section, be sure to handle
'set' magic properly.  See L<perlguts> for details about 'set' magic.

当在PPCODE节中处理输出参数的时候,一定适当要处理'set'魔法。参见L<perlguts>以查看更多关于'set'魔法的细节。

=head2 Returning Undef And Empty Lists

=head2 返回 Undef和空列表

Occasionally the programmer will want to return simply
C<undef> or an empty list if a function fails rather than a
separate status value.  The rpcb_gettime() function offers
just this situation.  If the function succeeds we would like
to have it return the time and if it fails we would like to
have undef returned.  In the following Perl code the value
of $timep will either be undef or it will be a valid time.

有的时候当函数调用失败,程序员期望返回C<undef>或一个空列表而不是状态码。
rpcb_gettime()正好提供了这种场景。如果函数成功,我们期望返回时间,如果失败,我们期望返回undef。
在一下Perl代码$time的值要么是undef要么是一个合法时间。

     $timep = rpcb_gettime( "localhost" );

The following XSUB uses the C<SV *> return type as a mnemonic only,
and uses a CODE: block to indicate to the compiler
that the programmer has supplied all the necessary code.  The
sv_newmortal() call will initialize the return value to undef, making that
the default return value.

以下XSUB只为了记忆方便使用C<SV *>返回类型,
并使用CODE: 块向编译器表明程序员已经提供了所有必要的代码。
sv_newmortal()调用将会将返回值初始化为undef,将其设为默认值。


     SV *
     rpcb_gettime(host)
          char *  host
	PREINIT:
          time_t  timep;
          bool_t x;
        CODE:
          ST(0) = sv_newmortal();
          if( rpcb_gettime( host, &timep ) )
               sv_setnv( ST(0), (double)timep);

The next example demonstrates how one would place an explicit undef in the
return value, should the need arise.

下一个例子表明在特定条件下,如何显式的在返回值中放置一个undef值。

     SV *
     rpcb_gettime(host)
          char *  host
	PREINIT:
          time_t  timep;
          bool_t x;
        CODE:
          if( rpcb_gettime( host, &timep ) ){
               ST(0) = sv_newmortal();
               sv_setnv( ST(0), (double)timep);
          }
          else{
               ST(0) = &PL_sv_undef;
          }

To return an empty list one must use a PPCODE: block and
then not push return values on the stack.

返回一个空列表必须使用PPCODE: 块,并且不向栈上压值。

     void
     rpcb_gettime(host)
          char *host
	PREINIT:
          time_t  timep;
        PPCODE:
          if( rpcb_gettime( host, &timep ) )
               PUSHs(sv_2mortal(newSViv(timep)));
          else{
	      /* Nothing pushed on stack, so an empty
	       * list is implicitly returned. */
          }

Some people may be inclined to include an explicit C<return> in the above
XSUB, rather than letting control fall through to the end.  In those
situations C<XSRETURN_EMPTY> should be used, instead.  This will ensure that
the XSUB stack is properly adjusted.  Consult L<perlapi> for other
C<XSRETURN> macros.

一些人也许会倾向于在以上XSUB代码中显式包含一个C<return>,而不是将控制持续到最后。
着这些场景中应当使用C<XSRETURN_EMPTY>代替。这将会确保XSUB栈适当地做适应。
查询L<perlapi>以获取其他的C<XSRETURN>宏。

Since C<XSRETURN_*> macros can be used with CODE blocks as well, one can
rewrite this example as:

由于C<XSRETURN_*>宏可以在CODE块中使用,你可以将这个例子重写为:

     int
     rpcb_gettime(host)
          char *host
	PREINIT:
          time_t  timep;
        CODE:
          RETVAL = rpcb_gettime( host, &timep );
	  if (RETVAL == 0)
		XSRETURN_UNDEF;
	OUTPUT:
	  RETVAL

In fact, one can put this check into a POSTCALL: section as well.  Together
with PREINIT: simplifications, this leads to:

事实上,你可以将这个检查放到POSTCALL: 节中。和PREINIT: 简化在一起,就成了:

     int
     rpcb_gettime(host)
          char *host
          time_t  timep;
	POSTCALL:
	  if (RETVAL == 0)
		XSRETURN_UNDEF;

=head2 The REQUIRE: Keyword

=head2 REQUIRE: 关键字

The REQUIRE: keyword is used to indicate the minimum version of the
B<xsubpp> compiler needed to compile the XS module.  An XS module which
contains the following statement will compile with only B<xsubpp> version
1.922 or greater:

REQUIRE: 关键字被用于表明编译XS模块所需要的B<xsubpp>编译器的最小版本。
一个包含了以下声明的XS模块需要使用1.992即以上版本的B<xsubpp>编译器:

	REQUIRE: 1.922

=head2 The CLEANUP: Keyword

=head2 CLEANUP: 关键字

This keyword can be used when an XSUB requires special cleanup procedures
before it terminates.  When the CLEANUP:  keyword is used it must follow
any CODE:, PPCODE:, or OUTPUT: blocks which are present in the XSUB.  The
code specified for the cleanup block will be added as the last statements
in the XSUB.

这个关键字在当XSUB在终止前需要特定清理过程的时候使用。当使用CLEANUP: 关键字的时候,
它必须要跟着XSUB中的任何CODE:, PPCODE:, 或 OUTPUT: 块。
清理块中的代码将会作为XSUB中最后的语句添加进去。

=head2 The POSTCALL: Keyword

=head2 POSTCALL: 关键字

This keyword can be used when an XSUB requires special procedures
executed after the C subroutine call is performed.  When the POSTCALL:
keyword is used it must precede OUTPUT: and CLEANUP: blocks which are
present in the XSUB.

当XSUB在C子例程执行完后需要执行特定的过程时使用这个关键字。
POSTCALL: 关键字使用时必须要置于OUTPUT: 和CLEANUP: 块之前。

See examples in L<"The NO_OUTPUT Keyword"> and L<"Returning Undef And Empty Lists">.

参见L<NO_OUTPUT关键字>和<返回Undef和空列表>中的例子。

The POSTCALL: block does not make a lot of sense when the C subroutine
call is supplied by user by providing either CODE: or PPCODE: section.

当用户通过提供CODE: 扩PPCODE: 块调用C子例程的时候POSTCALL: 块不会起什么作用。

=head2 The BOOT: Keyword

=head2 BOOT: 关键字

The BOOT: keyword is used to add code to the extension's bootstrap
function.  The bootstrap function is generated by the B<xsubpp> compiler and
normally holds the statements necessary to register any XSUBs with Perl.
With the BOOT: keyword the programmer can tell the compiler to add extra
statements to the bootstrap function.

BOOT: 关键字被用于为拓展模块的启动函数添加代码。启动函数由B<xsubpp>编译器生成,
一般包含了向Perl注册XSUB的必要语句。有了BOOT: 关键字,程序员就可以告知编译器为启动函数添加额外的语句。

This keyword may be used any time after the first MODULE keyword and should
appear on a line by itself.  The first blank line after the keyword will
terminate the code block.

这个关键字可以出现在任何第一个MODULE关键字出现的地方之后,并且应该独占一行。
关键字之后的第一个空行会将这个代码块终止。

     BOOT:
     # The following message will be printed when the
     # bootstrap function executes.
     printf("Hello from the bootstrap!\n");

=head2 The VERSIONCHECK: Keyword

=head2 VERSIONCHECK: 关键字

The VERSIONCHECK: keyword corresponds to B<xsubpp>'s C<-versioncheck> and
C<-noversioncheck> options.  This keyword overrides the command line
options.  Version checking is enabled by default.  When version checking is
enabled the XS module will attempt to verify that its version matches the
version of the PM module.

VERSIONCHECK: 关键字对应于B<xsubpp>的C<-versioncheck>和C<-noversioncheck>选项。
这个关键字覆盖了命令行的选项。版本检查是默认被打开的。
打开后XS模块将会试图检验它的版本是否匹配PM模块的版本。

To enable version checking:

要打开版本检查的话:

    VERSIONCHECK: ENABLE

To disable version checking:

要关闭版本检查的话:

    VERSIONCHECK: DISABLE

Note that if the version of the PM module is an NV (a floating point
number), it will be stringified with a possible loss of precision
(currently chopping to nine decimal places) so that it may not match
the version of the XS module anymore. Quoting the $VERSION declaration
to make it a string is recommended if long version numbers are used.

注意,如果PM模块的版本号是一个NV(一个浮点数),它将会被转为字符串并可能丢失精度
(目前是被截取为9位数字),因此它可能与XS模块的版本号不匹配。当过长的版本号数字使用的时候,
推荐将$VERSION声明用引号包含起来,将其转为一个字符串。

=head2 The PROTOTYPES: Keyword

=head2 PROTOTYPES: 关键字

The PROTOTYPES: keyword corresponds to B<xsubpp>'s C<-prototypes> and
C<-noprototypes> options.  This keyword overrides the command line options.
Prototypes are enabled by default.  When prototypes are enabled XSUBs will
be given Perl prototypes.  This keyword may be used multiple times in an XS
module to enable and disable prototypes for different parts of the module.

PROTOTYPES: 关键字对应B<xsubpp>的C<-prototypes>和C<-noprototypes>选项。
这个关键字覆盖了命令行的选项。原型是默认打开的。当打开原型后XSUB将被给予Perl的原型。
这个关键字可能会在XS中使用多次,以在模块的不同部分打开或关闭原型。

To enable prototypes:

需要打开原型的话:

    PROTOTYPES: ENABLE

To disable prototypes:

需要关闭原型的话:

    PROTOTYPES: DISABLE

=head2 The PROTOTYPE: Keyword

=head2 PROTOTYPE: 关键字

This keyword is similar to the PROTOTYPES: keyword above but can be used to
force B<xsubpp> to use a specific prototype for the XSUB.  This keyword
overrides all other prototype options and keywords but affects only the
current XSUB.  Consult L<perlsub/Prototypes> for information about Perl
prototypes.

这个关键字类似于上面的PROTOTYPES: 关键字,但是可以被用于强制B<xsubpp>为XSUB使用特定的原型。
这个关键字覆盖所有其他的原型选项以及关键字,但是只影响当前的XSUB。参见L<perlxub/Prototypes>
以获得更多关于Perl原型的信息。

    bool_t
    rpcb_gettime(timep, ...)
          time_t timep = NO_INIT
	PROTOTYPE: $;$
	PREINIT:
          char *host = "localhost";
        CODE:
		  if( items > 1 )
		       host = (char *)SvPV_nolen(ST(1));
		  RETVAL = rpcb_gettime( host, &timep );
        OUTPUT:
          timep
          RETVAL

If the prototypes are enabled, you can disable it locally for a given
XSUB as in the following example:

如果这些原型被打开了,你可以在本地为某个XSUB关闭它,例如:

    void
    rpcb_gettime_noproto()
        PROTOTYPE: DISABLE
    ...

=head2 The ALIAS: Keyword

=head2 ALIAS: 关键字

The ALIAS: keyword allows an XSUB to have two or more unique Perl names
and to know which of those names was used when it was invoked.  The Perl
names may be fully-qualified with package names.  Each alias is given an
index.  The compiler will setup a variable called C<ix> which contain the
index of the alias which was used.  When the XSUB is called with its
declared name C<ix> will be 0.

ALIAS: 关键字允许XSUB有两个或以上独立的Perl中的名称,并知道在被调用的时候用的是哪个名称。
Perl中的名称可能是指定了完整包名的。每一个匿名都有一个索引。编译器将会创建一个C<ix>变量
包含了使用的匿名的索引。当XSUB被它声明的名字调用的时候C<ix>将是0。

The following example will create aliases C<FOO::gettime()> and
C<BAR::getit()> for this function.

以下例子将会为这个函数创建匿名C<FOO::gettime(0>和C<BAR::getit()>。

    bool_t
    rpcb_gettime(host,timep)
          char *host
          time_t &timep
	ALIAS:
	    FOO::gettime = 1
	    BAR::getit = 2
	INIT:
	  printf("# ix = %d\n", ix );
        OUTPUT:
          timep

=head2 The OVERLOAD: Keyword

=head2 OVERLOAD: 关键字

Instead of writing an overloaded interface using pure Perl, you
can also use the OVERLOAD keyword to define additional Perl names
for your functions (like the ALIAS: keyword above).  However, the
overloaded functions must be defined with three parameters (except
for the nomethod() function which needs four parameters).  If any
function has the OVERLOAD: keyword, several additional lines
will be defined in the c file generated by xsubpp in order to
register with the overload magic.

除了用纯Perl写一个被覆盖的接口,你也可以使用OVERLOAD关键字来为你的函数定义额外的Perl名称(就像上面提到的ALIAS: 关键字)。
然而,被覆盖的函数必须被定义为有三个参数(除了nomethod()函数需要四个参数)。
如果任何函数有OVERLOAD: 关键字,几行额外的代码将被定义到xsubpp生成的C文件中以注册"覆盖"魔法。

Since blessed objects are actually stored as RV's, it is useful
to use the typemap features to preprocess parameters and extract
the actual SV stored within the blessed RV.  See the sample for
T_PTROBJ_SPECIAL below.

由于blessed的对象一般存在RV中,可以使用typemap特性来对参数进行预处理并将储存在RV中的SV释放出来。
参见下面T_PTROBJ_SPECIAL的例子。

To use the OVERLOAD: keyword, create an XS function which takes
three input parameters ( or use the c style '...' definition) like
this:

为了使用OVERLOAD: 关键字,创建一个有三个输入参数的XS函数(或者使用C风格的'...'定义),像这样:

    SV *
    cmp (lobj, robj, swap)
    My_Module_obj    lobj
    My_Module_obj    robj
    IV               swap
    OVERLOAD: cmp <=>
    { /* function defined here */}

In this case, the function will overload both of the three way
comparison operators.  For all overload operations using non-alpha
characters, you must type the parameter without quoting, separating
multiple overloads with whitespace.  Note that "" (the stringify
overload) should be entered as \"\" (i.e. escaped).

在这个例子中,这个函数将会覆盖全部两种三重比较操作符。对于所有使用非字母的覆盖操作,
你必须不带引号得输入参数,用空格将多个覆盖操作符分割开。注意""(字符串转换覆盖)应该以\"\"的形式
输入(i.e. 转意)。

=head2 The FALLBACK: Keyword

=head2 FALLBACK: 关键字

In addition to the OVERLOAD keyword, if you need to control how
Perl autogenerates missing overloaded operators, you can set the
FALLBACK keyword in the module header section, like this:

除了OVERLOAD关键字,如果你需要控制Perl自动生成丢失的覆盖操作符,
你可以在模块的头段中设置FALLBACK关键字,比如这样:

    MODULE = RPC  PACKAGE = RPC

    FALLBACK: TRUE
    ...

where FALLBACK can take any of the three values TRUE, FALSE, or
UNDEF.  If you do not set any FALLBACK value when using OVERLOAD,
it defaults to UNDEF.  FALLBACK is not used except when one or
more functions using OVERLOAD have been defined.  Please see
L<overload/fallback> for more details.

FALLBACK可以传入TRUE,FALSE或UNDEF中的任何一个。如果在使用OVERLOAD的时候没有设置任何FALLBACK关键字,
则默认为UNDEF。只有当一个或多个函数使用OVERLOAD的时候才需要使用FALLBACK。请参见L<overload/fallback>以获取更多细节。

=head2 The INTERFACE: Keyword

=head2 INTERFACE: 关键字

This keyword declares the current XSUB as a keeper of the given
calling signature.  If some text follows this keyword, it is
considered as a list of functions which have this signature, and
should be attached to the current XSUB.

这个关键字将当前XSUB声明为给定调用签名的保持者。如果在这个关键字后面还有一些文本,
它被看作是拥有这个签名的函数列表,并且被附着到当前XSUB上了。

For example, if you have 4 C functions multiply(), divide(), add(),
subtract() all having the signature:

例如,如果你有四个C函数multiply(), divide(), add(), subtract(),它们都有签名:

    symbolic f(symbolic, symbolic);

you can make them all to use the same XSUB using this:

如果你让它们使用同样的XSUB,则这样使用:

    symbolic
    interface_s_ss(arg1, arg2)
	symbolic	arg1
	symbolic	arg2
    INTERFACE:
	multiply divide
	add subtract

(This is the complete XSUB code for 4 Perl functions!)  Four generated
Perl function share names with corresponding C functions.

(这是一段4个Perl函数的完整XSUB!)四个生成的Perl函数将会分享对应名字的C函数。

The advantage of this approach comparing to ALIAS: keyword is that there
is no need to code a switch statement, each Perl function (which shares
the same XSUB) knows which C function it should call.  Additionally, one
can attach an extra function remainder() at runtime by using

这种方式相比于ALIAS: 关键字的好处是不再需要写转换场景的代码了,每一个Perl函数(分享同一个XSUB)
知道哪一个C函数它应当调用。除此之外,你可以这样在运行时附着上一个额外的函数remainder():

    CV *mycv = newXSproto("Symbolic::remainder",
			  XS_Symbolic_interface_s_ss, __FILE__, "$$");
    XSINTERFACE_FUNC_SET(mycv, remainder);

say, from another XSUB.  (This example supposes that there was no
INTERFACE_MACRO: section, otherwise one needs to use something else instead of
C<XSINTERFACE_FUNC_SET>, see the next section.)

也就是说,从另一个XSUB中。(这个例子假设没有INTERFACE_MACRO: 节,否则的话就需要做
其他一些事情而不是C<XSINTERFACE_FUNC_SET>,请看下一节。)

=head2 The INTERFACE_MACRO: Keyword

=head2 INTERFACE_MACRO: 关键字

This keyword allows one to define an INTERFACE using a different way
to extract a function pointer from an XSUB.  The text which follows
this keyword should give the name of macros which would extract/set a
function pointer.  The extractor macro is given return type, C<CV*>,
and C<XSANY.any_dptr> for this C<CV*>.  The setter macro is given cv,
and the function pointer.

这个关键字允许用另一种方式定义一个INTERFACE以从XSUB中释放出一个函数指针。
这个关键字后面跟的文本应该给出用于设置或释放函数指针的宏的名字。
这个释放宏被指定了返回类型C<CV*>,和 这个 C<CV*>的C<XSANY.any_dptr>。
设置宏被指定了cv以及函数指针。 

The default value is C<XSINTERFACE_FUNC> and C<XSINTERFACE_FUNC_SET>.
An INTERFACE keyword with an empty list of functions can be omitted if
INTERFACE_MACRO keyword is used.

默认值为C<XSINTERFACE_FUNC> 和 C<XSINTERFACE_FUNC_SET>。
如果使用了INTERFACE_MACRO关键字的话,那么一个函数列表为空的INTERFACE关键字可以被省略掉。

Suppose that in the previous example functions pointers for
multiply(), divide(), add(), subtract() are kept in a global C array
C<fp[]> with offsets being C<multiply_off>, C<divide_off>, C<add_off>,
C<subtract_off>.  Then one can use

加入在之前的例子中multiply(), divide(), add(), subtract()的函数指针位于一个全局C数组C<fp[]>中,
偏移分别为:C<multiply_off>, C<divide_off>, C<add_off>, C<subtract_off>。那么可以用:

    #define XSINTERFACE_FUNC_BYOFFSET(ret,cv,f) \
	((XSINTERFACE_CVT_ANON(ret))fp[CvXSUBANY(cv).any_i32])
    #define XSINTERFACE_FUNC_BYOFFSET_set(cv,f) \
	CvXSUBANY(cv).any_i32 = CAT2( f, _off )

in C section,

在C的段中。

    symbolic
    interface_s_ss(arg1, arg2)
	symbolic	arg1
	symbolic	arg2
      INTERFACE_MACRO:
	XSINTERFACE_FUNC_BYOFFSET
	XSINTERFACE_FUNC_BYOFFSET_set
      INTERFACE:
	multiply divide
	add subtract

in XSUB section.

在XSUB 的段中。

=head2 The INCLUDE: Keyword

=head2: INCLUDE: 关键字

This keyword can be used to pull other files into the XS module.  The other
files may have XS code.  INCLUDE: can also be used to run a command to
generate the XS code to be pulled into the module.

这个关键字用于将其他文件中的内容加到XS模块中。其他文件也许有XS代码。
INCLUDE: 同样可以用于运行一个命令以生成需要添加到模块中的XS代码。

The file F<Rpcb1.xsh> contains our C<rpcb_gettime()> function:

文件F<Rpcb1.xsh>包含了我们的C<rpcb_gettime()>函数:

    bool_t
    rpcb_gettime(host,timep)
          char *host
          time_t &timep
        OUTPUT:
          timep

The XS module can use INCLUDE: to pull that file into it.

XS模块可以使用INCLUDE: 将这个文件的内容添加进来。

    INCLUDE: Rpcb1.xsh

If the parameters to the INCLUDE: keyword are followed by a pipe (C<|>) then
the compiler will interpret the parameters as a command. This feature is
mildly deprecated in favour of the C<INCLUDE_COMMAND:> directive, as documented
below.

如果INCLUDE: 关键字跟着一个管道符(C<|>)那么编译器将会将参数解释为命令。这个特性差不多被
废除了,因为现在有C<INCLUDE_COMMAND:>条目了,如下所述。

    INCLUDE: cat Rpcb1.xsh |

Do not use this to run perl: C<INCLUDE: perl |> will run the perl that
happens to be the first in your path and not necessarily the same perl that is
used to run C<xsubpp>. See L<"The INCLUDE_COMMAND: Keyword">.

如果不使用这个来运行perl: C<INCLUDE: perl |>将会运行搜索路径下的第一个perl,并且不一定是
运行C<xsubpp>的perl。参见 L<"INCLUDE_COMMAND: 关键字">。

=head2 The INCLUDE_COMMAND: Keyword

=head2 INCLUDE_COMMAND: 关键字

Runs the supplied command and includes its output into the current XS
document. C<INCLUDE_COMMAND> assigns special meaning to the C<$^X> token
in that it runs the same perl interpreter that is running C<xsubpp>:

运行提供的命令,并将输出包含到当前的XS文档中。C<INCLUDE_COMMAND>给予C<$^X>符号特殊的意义:
运行当前的C<xsubpp>的同样的perl解释器。

    INCLUDE_COMMAND: cat Rpcb1.xsh

    INCLUDE_COMMAND: $^X -e ...

=head2 The CASE: Keyword

=head2 CASE: 关键字

The CASE: keyword allows an XSUB to have multiple distinct parts with each
part acting as a virtual XSUB.  CASE: is greedy and if it is used then all
other XS keywords must be contained within a CASE:.  This means nothing may
precede the first CASE: in the XSUB and anything following the last CASE: is
included in that case.

CASE: 关键字允许XSUB有对个分支部分,每个部分像是一个虚XSUB。
CASE: 是贪心的,如果它被使用了那么其他所有的XS关键字都必须包含在一个CASE: 中。
这意味着没有什么能在第一个CASE: 之前。在XSUB中任何在最后一个CASE: 之后的内容都在那个case中。

A CASE: might switch via a parameter of the XSUB, via the C<ix> ALIAS:
variable (see L<"The ALIAS: Keyword">), or maybe via the C<items> variable
(see L<"Variable-length Parameter Lists">).  The last CASE: becomes the
B<default> case if it is not associated with a conditional.  The following
example shows CASE switched via C<ix> with a function C<rpcb_gettime()>
having an alias C<x_gettime()>.  When the function is called as
C<rpcb_gettime()> its parameters are the usual C<(char *host, time_t *timep)>,
but when the function is called as C<x_gettime()> its parameters are
reversed, C<(time_t *timep, char *host)>.

CASE: 通过XSUB的参数,或者C<ix> ALIAS: 变量<参见 L<"ALIAS: 关键字">>,或者通过C<items>变量
(参见L<"变长参数列表">)来确定使用的分支。最后一个CASE: 如果没有关联条件的话就成为了默认场景。
以下例子展示了CASE 根据函数C<rpcb_gettime()>和它的匿名函数<x_gettime()>的C<ix>变量进行分支。
当函数作为C<rpcb_gettime()>被调用,它的参数是通常的C<(char *host, time_t *timep)>,
但是当函数被C<x_gettime()>调用时,它的参数是反过来的,C<(time_t *timep, char *host)>。

    long
    rpcb_gettime(a,b)
      CASE: ix == 1
	ALIAS:
	  x_gettime = 1
	INPUT:
	  # 'a' is timep, 'b' is host
          char *b
          time_t a = NO_INIT
        CODE:
               RETVAL = rpcb_gettime( b, &a );
        OUTPUT:
          a
          RETVAL
      CASE:
	  # 'a' is host, 'b' is timep
          char *a
          time_t &b = NO_INIT
        OUTPUT:
          b
          RETVAL

That function can be called with either of the following statements.  Note
the different argument lists.

那个函数可以通过下面任意一种方式调用。注意不同的参数列表。

	$status = rpcb_gettime( $host, $timep );

	$status = x_gettime( $timep, $host );

=head2 The EXPORT_XSUB_SYMBOLS: Keyword

=head2 EXPORT_XSUB_SYMBOLS: 关键字

The EXPORT_XSUB_SYMBOLS: keyword is likely something you will never need.
In perl versions earlier than 5.16.0, this keyword does nothing. Starting
with 5.16, XSUB symbols are no longer exported by default. That is, they
are C<static> functions. If you include

EXPORT_XSUB_SYMBOLS: 关键字你差不多永远都不会用到。
在perl 5.16.0以前的版本中,这个关键字什么都不做。从5.16开始,XSUB的符号不再是默认导出的了。
也就是说,它们是静态函数。如果你包含了

  EXPORT_XSUB_SYMBOLS: ENABLE

in your XS code, the XSUBs following this line will not be declared C<static>.
You can later disable this with

在你的XS代码中,在这一行以后的XSUB不再被声明为C<static>。
你可以在后面再将它关闭:

  EXPORT_XSUB_SYMBOLS: DISABLE

which, again, is the default that you should probably never change.
You cannot use this keyword on versions of perl before 5.16 to make
XSUBs C<static>.

这样,也就是默认的情况,你最好不要改变它。
在5.16以前的版本你无法通过这个关键字将XSUB变为C<static>。

=head2 The & Unary Operator

=head2 &一元操作符

The C<&> unary operator in the INPUT: section is used to tell B<xsubpp>
that it should convert a Perl value to/from C using the C type to the left
of C<&>, but provide a pointer to this value when the C function is called.

C<&> 一元操作副在INPUT: 段中是告诉B<xsubpp>,它应该将一个Perl的转到C或从C转入为C<&>左边的C
类型,但是当C函数被调用的时候提供了一个指向这个值的指针。


This is useful to avoid a CODE: block for a C function which takes a parameter
by reference.  Typically, the parameter should be not a pointer type (an
C<int> or C<long> but not an C<int*> or C<long*>).

这个对于通过引用传一个参数的C函数来说可以用于避免使用CODE: 块。

The following XSUB will generate incorrect C code.  The B<xsubpp> compiler will
turn this into code which calls C<rpcb_gettime()> with parameters C<(char
*host, time_t timep)>, but the real C<rpcb_gettime()> wants the C<timep>
parameter to be of type C<time_t*> rather than C<time_t>.

以下XSUB会生成错误的C代码。B<xsubpp>编译器将会将其转为使用C<(char
*host, time_t timep)>参数来调用C<rpcb_gettime()>的代码,但是C<rpcb_gettime()>
的参数C<timep>实际上希望的是C<time_t*>而不是C<time_t>

    bool_t
    rpcb_gettime(host,timep)
          char *host
          time_t timep
        OUTPUT:
          timep

That problem is corrected by using the C<&> operator.  The B<xsubpp> compiler
will now turn this into code which calls C<rpcb_gettime()> correctly with
parameters C<(char *host, time_t *timep)>.  It does this by carrying the
C<&> through, so the function call looks like C<rpcb_gettime(host, &timep)>.

这个问题可以通过C<&>操作符修正。B<xsubpp>编译器将会将其转为正确地使用C<(char *host, time_t *timep)>
参数调用C<rpcb_gettime()>的代码。它通过携带C<&>做到这样,因此函数调用看起来像C<rpcb_gettime(host, &timep)>。

    bool_t
    rpcb_gettime(host,timep)
          char *host
          time_t &timep
        OUTPUT:
          timep

=head2 Inserting POD, Comments and C Preprocessor Directives

=head2 插入POD,注释和C预处理指令

C preprocessor directives are allowed within BOOT:, PREINIT: INIT:, CODE:,
PPCODE:, POSTCALL:, and CLEANUP: blocks, as well as outside the functions.
Comments are allowed anywhere after the MODULE keyword.  The compiler will
pass the preprocessor directives through untouched and will remove the
commented lines. POD documentation is allowed at any point, both in the
C and XS language sections. POD must be terminated with a C<=cut> command;
C<xsubpp> will exit with an error if it does not. It is very unlikely that
human generated C code will be mistaken for POD, as most indenting styles
result in whitespace in front of any line starting with C<=>. Machine
generated XS files may fall into this trap unless care is taken to
ensure that a space breaks the sequence "\n=".

在BOOT: ,PREINIT: ,INIT: ,CODE: ,PPCODE: ,POSTCALL: ,和CLEANUP: 块中
和在函数外一样可以使用C预处理指令。在MODULE关键字之后可以使用注释。
编译器将会不会处理预处理指令,并且将注释行移除。POD文档允许存在任何地方,包括C和XS语言的段。
POD必须以C<=cut>结尾;如果你不这样做的话C<xsubpp>将会错误退出。
人写的代码不太可能被误认为是POD,因为大部分缩进形式都是在以C<=>开头的行前的空格。
机器生成的XS文件可能会陷入陷阱,除非保证用空格打断"\n="序列。

Comments can be added to XSUBs by placing a C<#> as the first
non-whitespace of a line.  Care should be taken to avoid making the
comment look like a C preprocessor directive, lest it be interpreted as
such.  The simplest way to prevent this is to put whitespace in front of
the C<#>.

可以通过在一行的第一个非空白字符放置C<#>来为XSUB添加注释。
注意要避免看起来像C预处理指令的注释。最简单的避免方式是在C<#>前添加空格。

If you use preprocessor directives to choose one of two
versions of a function, use

如果你使用预处理指令选择一个函数的版本,使用

    #if ... version1
    #else /* ... version2  */
    #endif

and not

而不是

    #if ... version1
    #endif
    #if ... version2
    #endif

because otherwise B<xsubpp> will believe that you made a duplicate
definition of the function.  Also, put a blank line before the
#else/#endif so it will not be seen as part of the function body.

因为否则的话B<xsubpp>将会认为你重复定义了一个函数。另外,在#else/#endif前放一空行,
这样它才不会被认为是函数体的一部分。

=head2 Using XS With C++

=head2 XS和C++联合使用

If an XSUB name contains C<::>, it is considered to be a C++ method.
The generated Perl function will assume that
its first argument is an object pointer.  The object pointer
will be stored in a variable called THIS.  The object should
have been created by C++ with the new() function and should
be blessed by Perl with the sv_setref_pv() macro.  The
blessing of the object by Perl can be handled by a typemap.  An example
typemap is shown at the end of this section.

If the return type of the XSUB includes C<static>, the method is considered
to be a static method.  It will call the C++
function using the class::method() syntax.  If the method is not static
the function will be called using the THIS-E<gt>method() syntax.

The next examples will use the following C++ class.

     class color {
          public:
          color();
          ~color();
          int blue();
          void set_blue( int );

          private:
          int c_blue;
     };

The XSUBs for the blue() and set_blue() methods are defined with the class
name but the parameter for the object (THIS, or "self") is implicit and is
not listed.

     int
     color::blue()

     void
     color::set_blue( val )
          int val

Both Perl functions will expect an object as the first parameter.  In the
generated C++ code the object is called C<THIS>, and the method call will
be performed on this object.  So in the C++ code the blue() and set_blue()
methods will be called as this:

     RETVAL = THIS->blue();

     THIS->set_blue( val );

You could also write a single get/set method using an optional argument:

     int
     color::blue( val = NO_INIT )
         int val
         PROTOTYPE $;$
         CODE:
             if (items > 1)
                 THIS->set_blue( val );
             RETVAL = THIS->blue();
         OUTPUT:
             RETVAL

If the function's name is B<DESTROY> then the C++ C<delete> function will be
called and C<THIS> will be given as its parameter.  The generated C++ code for

     void
     color::DESTROY()

will look like this:

     color *THIS = ...;	// Initialized as in typemap

     delete THIS;

If the function's name is B<new> then the C++ C<new> function will be called
to create a dynamic C++ object.  The XSUB will expect the class name, which
will be kept in a variable called C<CLASS>, to be given as the first
argument.

     color *
     color::new()

The generated C++ code will call C<new>.

     RETVAL = new color();

The following is an example of a typemap that could be used for this C++
example.

    TYPEMAP
    color *		O_OBJECT

    OUTPUT
    # The Perl object is blessed into 'CLASS', which should be a
    # char* having the name of the package for the blessing.
    O_OBJECT
	sv_setref_pv( $arg, CLASS, (void*)$var );

    INPUT
    O_OBJECT
	if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
		$var = ($type)SvIV((SV*)SvRV( $arg ));
	else{
		warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
		XSRETURN_UNDEF;
	}

=head2 Interface Strategy

=head2 接口策略

When designing an interface between Perl and a C library a straight
translation from C to XS (such as created by C<h2xs -x>) is often sufficient.
However, sometimes the interface will look
very C-like and occasionally nonintuitive, especially when the C function
modifies one of its parameters, or returns failure inband (as in "negative
return values mean failure").  In cases where the programmer wishes to
create a more Perl-like interface the following strategy may help to
identify the more critical parts of the interface.

当设计一个Perl与C库之间的接口的时候,将C直接转换为XS(就像C<h2xs -x>创建的那样)
通常是非常高效的。然而,这样生成的接口往往看上去有明显的C风格从而不够直观,
尤其是当C函数修改它的一个参数的时候,或者返回失败(比如“返回负数表示失败”)。
如果程序员希望能创建更加Perl风格的接口时,一下策略对于制定接口的原则会有帮助。

Identify the C functions with input/output or output parameters.  The XSUBs for
these functions may be able to return lists to Perl.

对于有输入/输出 或 输出参数的C函数。XSUB应该返回列表给Perl。

Identify the C functions which use some inband info as an indication
of failure.  They may be
candidates to return undef or an empty list in case of failure.  If the
failure may be detected without a call to the C function, you may want to use
an INIT: section to report the failure.  For failures detectable after the C
function returns one may want to use a POSTCALL: section to process the
failure.  In more complicated cases use CODE: or PPCODE: sections.

对于使用返回值标识失败的C函数。应该在失败时返回undef或空列表。
如果在调用C函数前就可以检查出失败,你也许想用INIT: 节来报告失败。
对于在C函数调用完成后才检查出来的错误你也许想用POSTCALL: 节处理。
在更加复杂的例子中用CODE: 或 PPCODE: 节。

If many functions use the same failure indication based on the return value,
you may want to create a special typedef to handle this situation.  Put

很多函数根据返回值返回同样的失败,你可以创建一个特殊的typedef来处理这种场景。
将

  typedef int negative_is_failure;

near the beginning of XS file, and create an OUTPUT typemap entry
for C<negative_is_failure> which converts negative values to C<undef>, or
maybe croak()s.  After this the return value of type C<negative_is_failure>
will create more Perl-like interface.

放置到XS文件的开头,然后为C<negative_is_failure>创建一个OUTPUT typemap条目以将负数转为C<undef>,
或者croak()之类的。在这之后C<negative_is_failure>类型的返回值将会创建更加Perl风格的接口。

Identify which values are used by only the C and XSUB functions
themselves, say, when a parameter to a function should be a contents of a
global variable.  If Perl does not need to access the contents of the value
then it may not be necessary to provide a translation for that value
from C to Perl.

对于那些只被C和XSUB函数使用的值,比如,函数的参数是某个全局变量。
如果Perl不需要访问这些值,那么就没有必要提供将这些值从C转为Perl的转换。

Identify the pointers in the C function parameter lists and return
values.  Some pointers may be used to implement input/output or
output parameters, they can be handled in XS with the C<&> unary operator,
and, possibly, using the NO_INIT keyword.
Some others will require handling of types like C<int *>, and one needs
to decide what a useful Perl translation will do in such a case.  When
the semantic is clear, it is advisable to put the translation into a typemap
file.

对于C函数参数列表或返回值中有指针的。一些指针可能被用于输入输出参数,
它们可以在XS中通过C<&>操作符处理,而且可能会使用NO_INIT关键字。
一些场景下需要处理类似于C<int *>之类的类型,你需要确定怎么做与Perl类型的转化。
当语义明确的时候,最好将转换代码放到typemap文件中。

Identify the structures used by the C functions.  In many
cases it may be helpful to use the T_PTROBJ typemap for
these structures so they can be manipulated by Perl as
blessed objects.  (This is handled automatically by C<h2xs -x>.)

在C函数使用结构体的场景下。很多时候可以将T_PTROBJ typemap用于这些结构体,
这样它们就可以被Perl以blessed对象管理了。(这个是被C<h2xs -x>自动处理的)

If the same C type is used in several different contexts which require
different translations, C<typedef> several new types mapped to this C type,
and create separate F<typemap> entries for these new types.  Use these
types in declarations of return type and parameters to XSUBs.

当同样的C类型在不同的上下文中使用需要不同的转换方式时,C<typedef>多个新的类型映射到C类型上,
然后为它们创建不同的F<typemap>条目。使用在声明XSUB的返回值和参数的时候用这些类型。

=head2 Perl Objects And C Structures

=head2 Perl 对象和C结构体

When dealing with C structures one should select either
B<T_PTROBJ> or B<T_PTRREF> for the XS type.  Both types are
designed to handle pointers to complex objects.  The
T_PTRREF type will allow the Perl object to be unblessed
while the T_PTROBJ type requires that the object be blessed.
By using T_PTROBJ one can achieve a form of type-checking
because the XSUB will attempt to verify that the Perl object
is of the expected type.

当处理C结构体的时候,你应当为XS类型选择B<T_PTROBJ>或B<T_PTRREF>。
这些类型被设计用于处理指向复杂对象的指针。T_PTRREF 类型允许Perl对象是unblessed的而T_PTROBJ类型
需要对象是blessed的。通过使用T_PTROBJ你可以实现某种形式的类型检查,因为XSUB将会检验Perl对象
是否是所期待的类型。

The following XS code shows the getnetconfigent() function which is used
with ONC+ TIRPC.  The getnetconfigent() function will return a pointer to a
C structure and has the C prototype shown below.  The example will
demonstrate how the C pointer will become a Perl reference.  Perl will
consider this reference to be a pointer to a blessed object and will
attempt to call a destructor for the object.  A destructor will be
provided in the XS source to free the memory used by getnetconfigent().
Destructors in XS can be created by specifying an XSUB function whose name
ends with the word B<DESTROY>.  XS destructors can be used to free memory
which may have been malloc'd by another XSUB.

以下XS代码展示了用于ONC+ TRIPC的getnetconfigent()函数。该函数会返回一个指向C结构体的指针,
其C原型如下。这个例子将会展示C指针是如何变成Perl引用的。Perl将会把这个引用认为是指向一个blessed
的对象的指针并且试图调用对象的析构函数。XS源码将提供析构函数以释放getnetconfigent()使用的内存。
XS中的析构函数可以通过创建一个以B<DESTROY>结尾的XSUB函数来实现。XS析构可以用来释放可能是
另一个XSUB申请的内存。

     struct netconfig *getnetconfigent(const char *netid);

A C<typedef> will be created for C<struct netconfig>.  The Perl
object will be blessed in a class matching the name of the C
type, with the tag C<Ptr> appended, and the name should not
have embedded spaces if it will be a Perl package name.  The
destructor will be placed in a class corresponding to the
class of the object and the PREFIX keyword will be used to
trim the name to the word DESTROY as Perl will expect.

将会为C<struct_netconfig>创建一个C<typedef>。Perl对象将会被blessed到一个匹配C类型名称的class上,
外带添加一个C<Ptr>标签,名字如果是一个Perl包名的话,则中间不应该有空格。
析构器将会被放置到对象对应的类中,而且PREFIX关键字将被用于修饰DESTROY,正如Perl所期望的。

     typedef struct netconfig Netconfig;

     MODULE = RPC  PACKAGE = RPC

     Netconfig *
     getnetconfigent(netid)
          char *netid

     MODULE = RPC  PACKAGE = NetconfigPtr  PREFIX = rpcb_

     void
     rpcb_DESTROY(netconf)
          Netconfig *netconf
        CODE:
          printf("Now in NetconfigPtr::DESTROY\n");
          free( netconf );

This example requires the following typemap entry.  Consult
L<perlxstypemap> for more information about adding new typemaps
for an extension.

这个例子需要以下typemap条目。参考L<perlxstypemap>以获得更多关于添加新的typemap拓展的信息。

     TYPEMAP
     Netconfig *  T_PTROBJ

This example will be used with the following Perl statements.

这个例子将被用于以下Perl语句。

     use RPC;
     $netconf = getnetconfigent("udp");

When Perl destroys the object referenced by $netconf it will send the
object to the supplied XSUB DESTROY function.  Perl cannot determine, and
does not care, that this object is a C struct and not a Perl object.  In
this sense, there is no difference between the object created by the
getnetconfigent() XSUB and an object created by a normal Perl subroutine.

当Perl销毁$netconf引用的对象时,它将会把这个对象发送给提供的XSUB DESTROY函数。
Perl无法决定,也不在乎这个对象是C结构体而不是Perl对象。
因此,getnetconfigent() XSUB函数创建的对象和普通Perl子例程创建的对象没有什么区别。

=head2 Safely Storing Static Data in XS

=head2 在XS中安全地储存静态数据

Starting with Perl 5.8, a macro framework has been defined to allow
static data to be safely stored in XS modules that will be accessed from
a multi-threaded Perl.

从5.8开始,定义了一个宏框架以允许静态数据被安全地存在XS模块中以被多线程的Perl访问。

Although primarily designed for use with multi-threaded Perl, the macros
have been designed so that they will work with non-threaded Perl as well.

尽管主要是为了给多线程的Perl使用,这些宏还是被设计可以在不支持线程的Perl中使用。

It is therefore strongly recommended that these macros be used by all
XS modules that make use of static data.

因此强烈推荐当XS模块需要静态数据的时候使用这些宏。

The easiest way to get a template set of macros to use is by specifying
the C<-g> (C<--global>) option with h2xs (see L<h2xs>).

最简单获取一个可用宏的模板集合的方法是使用h2xs的C<-g> (C<--global>)选项(参见L<h2xs>)。

Below is an example module that makes use of the macros.

以下是一个使用这些宏的例子模块。

    #include "EXTERN.h"
    #include "perl.h"
    #include "XSUB.h"

    /* Global Data */

    #define MY_CXT_KEY "BlindMice::_guts" XS_VERSION

    typedef struct {
        int count;
        char name[3][100];
    } my_cxt_t;

    START_MY_CXT

    MODULE = BlindMice           PACKAGE = BlindMice

    BOOT:
    {
        MY_CXT_INIT;
        MY_CXT.count = 0;
        strcpy(MY_CXT.name[0], "None");
        strcpy(MY_CXT.name[1], "None");
        strcpy(MY_CXT.name[2], "None");
    }

    int
    newMouse(char * name)
        char * name;
        PREINIT:
          dMY_CXT;
        CODE:
          if (MY_CXT.count >= 3) {
              warn("Already have 3 blind mice");
              RETVAL = 0;
          }
          else {
              RETVAL = ++ MY_CXT.count;
              strcpy(MY_CXT.name[MY_CXT.count - 1], name);
          }

    char *
    get_mouse_name(index)
      int index
      CODE:
        dMY_CXT;
        RETVAL = MY_CXT.lives ++;
        if (index > MY_CXT.count)
          croak("There are only 3 blind mice.");
        else
          RETVAL = newSVpv(MY_CXT.name[index - 1]);

    void
    CLONE(...)
	CODE:
	MY_CXT_CLONE;

B<REFERENCE>

=over 5

=item MY_CXT_KEY

This macro is used to define a unique key to refer to the static data
for an XS module. The suggested naming scheme, as used by h2xs, is to
use a string that consists of the module name, the string "::_guts"
and the module version number.

    #define MY_CXT_KEY "MyModule::_guts" XS_VERSION

=item typedef my_cxt_t

This struct typedef I<must> always be called C<my_cxt_t>. The other
C<CXT*> macros assume the existence of the C<my_cxt_t> typedef name.

Declare a typedef named C<my_cxt_t> that is a structure that contains
all the data that needs to be interpreter-local.

    typedef struct {
        int some_value;
    } my_cxt_t;

=item START_MY_CXT

Always place the START_MY_CXT macro directly after the declaration
of C<my_cxt_t>.

=item MY_CXT_INIT

The MY_CXT_INIT macro initialises storage for the C<my_cxt_t> struct.

It I<must> be called exactly once, typically in a BOOT: section. If you
are maintaining multiple interpreters, it should be called once in each
interpreter instance, except for interpreters cloned from existing ones.
(But see L</MY_CXT_CLONE> below.)

=item dMY_CXT

Use the dMY_CXT macro (a declaration) in all the functions that access
MY_CXT.

=item MY_CXT

Use the MY_CXT macro to access members of the C<my_cxt_t> struct. For
example, if C<my_cxt_t> is

    typedef struct {
        int index;
    } my_cxt_t;

then use this to access the C<index> member

    dMY_CXT;
    MY_CXT.index = 2;

=item aMY_CXT/pMY_CXT

C<dMY_CXT> may be quite expensive to calculate, and to avoid the overhead
of invoking it in each function it is possible to pass the declaration
onto other functions using the C<aMY_CXT>/C<pMY_CXT> macros, eg

    void sub1() {
	dMY_CXT;
	MY_CXT.index = 1;
	sub2(aMY_CXT);
    }

    void sub2(pMY_CXT) {
	MY_CXT.index = 2;
    }

Analogously to C<pTHX>, there are equivalent forms for when the macro is the
first or last in multiple arguments, where an underscore represents a
comma, i.e.  C<_aMY_CXT>, C<aMY_CXT_>, C<_pMY_CXT> and C<pMY_CXT_>.

=item MY_CXT_CLONE

By default, when a new interpreter is created as a copy of an existing one
(eg via C<< threads->create() >>), both interpreters share the same physical
my_cxt_t structure. Calling C<MY_CXT_CLONE> (typically via the package's
C<CLONE()> function), causes a byte-for-byte copy of the structure to be
taken, and any future dMY_CXT will cause the copy to be accessed instead.

=item MY_CXT_INIT_INTERP(my_perl)

=item dMY_CXT_INTERP(my_perl)

These are versions of the macros which take an explicit interpreter as an
argument.

=back

Note that these macros will only work together within the I<same> source
file; that is, a dMY_CTX in one source file will access a different structure
than a dMY_CTX in another source file.

=head2 Thread-aware system interfaces

Starting from Perl 5.8, in C/C++ level Perl knows how to wrap
system/library interfaces that have thread-aware versions
(e.g. getpwent_r()) into frontend macros (e.g. getpwent()) that
correctly handle the multithreaded interaction with the Perl
interpreter.  This will happen transparently, the only thing
you need to do is to instantiate a Perl interpreter.

This wrapping happens always when compiling Perl core source
(PERL_CORE is defined) or the Perl core extensions (PERL_EXT is
defined).  When compiling XS code outside of Perl core the wrapping
does not take place.  Note, however, that intermixing the _r-forms
(as Perl compiled for multithreaded operation will do) and the _r-less
forms is neither well-defined (inconsistent results, data corruption,
or even crashes become more likely), nor is it very portable.

=head1 EXAMPLES

File C<RPC.xs>: Interface to some ONC+ RPC bind library functions.

     #include "EXTERN.h"
     #include "perl.h"
     #include "XSUB.h"

     #include <rpc/rpc.h>

     typedef struct netconfig Netconfig;

     MODULE = RPC  PACKAGE = RPC

     SV *
     rpcb_gettime(host="localhost")
          char *host
	PREINIT:
          time_t  timep;
        CODE:
          ST(0) = sv_newmortal();
          if( rpcb_gettime( host, &timep ) )
               sv_setnv( ST(0), (double)timep );

     Netconfig *
     getnetconfigent(netid="udp")
          char *netid

     MODULE = RPC  PACKAGE = NetconfigPtr  PREFIX = rpcb_

     void
     rpcb_DESTROY(netconf)
          Netconfig *netconf
        CODE:
          printf("NetconfigPtr::DESTROY\n");
          free( netconf );

File C<typemap>: Custom typemap for RPC.xs. (cf. L<perlxstypemap>)

     TYPEMAP
     Netconfig *  T_PTROBJ

File C<RPC.pm>: Perl module for the RPC extension.

     package RPC;

     require Exporter;
     require DynaLoader;
     @ISA = qw(Exporter DynaLoader);
     @EXPORT = qw(rpcb_gettime getnetconfigent);

     bootstrap RPC;
     1;

File C<rpctest.pl>: Perl test program for the RPC extension.

     use RPC;

     $netconf = getnetconfigent();
     $a = rpcb_gettime();
     print "time = $a\n";
     print "netconf = $netconf\n";

     $netconf = getnetconfigent("tcp");
     $a = rpcb_gettime("poplar");
     print "time = $a\n";
     print "netconf = $netconf\n";


=head1 XS VERSION

This document covers features supported by C<ExtUtils::ParseXS>
(also known as C<xsubpp>) 3.13_01.

=head1 AUTHOR

Originally written by Dean Roehrich <F<roehrich@cray.com>>.

Maintained since 1996 by The Perl Porters <F<perlbug@perl.org>>.