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

📄 ch27.htm

📁 《Perl 5 Unreleased》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<HTML>



<HEAD>

   <TITLE>Chapter 27 -- Writing Extensions in C</TITLE>

   <META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">

</HEAD>

<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">

<H1><FONT COLOR=#FF0000>Chapter 27</FONT></H1>

<H1><B><FONT SIZE=5 COLOR=#FF0000>Writing Extensions in C</FONT></B>

</H1>

<P>

<HR WIDTH="100%"></P>

<P>

<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>

</FONT></FONT></H3>

<UL>

<LI><A HREF="#IntroductiontoXS" >Introduction to XS</A>

<LI><A HREF="#StepsforCreatinganExtension" >Steps for Creating an Extension</A>

<UL>

<LI><A HREF="#Step1ChangetothePerlDirectory" >Step 1: Change to the Perl Directory</A>

<LI><A HREF="#Step2Runh2sx" >Step 2: Run h2sx</A>

<LI><A HREF="#Step3CreateaMakefile" >Step 3: Create a Makefile</A>

<LI><A HREF="#Step4AddSomeCode" >Step 4: Add Some Code</A>

<LI><A HREF="#Step5TestYourExtensionModule" >Step 5: Test Your Extension Module</A>

<LI><A HREF="#FinalConsiderations" >Final Considerations</A>

</UL>

<LI><A HREF="#ThexsubppCompiler" >The xsubpp Compiler</A>

<LI><A HREF="#InputandOutputParameterstoFunctions" >Input and Output Parameters to Functions</A>

<UL>

<LI><A HREF="#ThetypemapFile" >The typemap File</A>

</UL>

<LI><A HREF="#ThebootstrapFunction" >The bootstrap Function</A>

<LI><A HREF="#PassingArguments" >Passing Arguments</A>

<LI><A HREF="#TheRETVALVariableandtheOUTPUTSecti" >The RETVAL Variable and the OUTPUT Section</A>

<LI><A HREF="#Keywords" >Keywords</A>

<UL>

<LI><A HREF="#TheMODULEKeyword" >The MODULE Keyword</A>

<LI><A HREF="#ThePACKAGEKeyword" >The PACKAGE Keyword</A>

<LI><A HREF="#TheCODEKeyword" >The CODE: Keyword</A>

<LI><A HREF="#TheOUTPUTKeyword" >The OUTPUT: Keyword</A>

<LI><A HREF="#PpcODEforReturningMoreThanOneValu" >PpcODE: for Returning More Than One Value</A>

<LI><A HREF="#ReturningUndefandEmptyLists" >Returning Undef and Empty Lists</A>

<LI><A HREF="#TheBOOTKeyword" >The BOOT: Keyword</A>

</UL>

<LI><A HREF="#TheListingsofModules" >The Listings of Modules</A>

<LI><A HREF="#Summary" >Summary</A>

</UL>

<HR>

<P>

In this chapter you'll work with the Perl XS<FONT FACE="AGaramond Bold">

</FONT>language, which is used to create an interface between

Perl and a C library. Such interfaces are called <I>extensions</I>

to Perl because they enable your code to look and feel just like

it is a part of Perl. Extensions are useful in appending extra

functionality to Perl. This chapter covers the basics of writing

extensions. The examples are simple enough to build on in order

to create your own extensions library.

<H2><A NAME="IntroductiontoXS"><B><FONT SIZE=5 COLOR=#FF0000>Introduction

to XS</FONT></B></A></H2>

<P>

In Perl, XS refers to a programming language interface used to

create an interface between C code and Perl scripts. Using the

XS API, you can create a library that can be loaded dynamically

into Perl.

<P>

The XS interface defines language components that wrap around

Perl constructs. To use the XS language, you need the <TT><FONT FACE="Courier">xsubpp</FONT></TT>

compiler to embed the constructs for you. The base construct in

the XS language is the <TT><FONT FACE="Courier">XSUB</FONT></TT>

function. The <TT><FONT FACE="Courier">XSUB</FONT></TT> function

is called when calls are made to pass data and control between

Perl and C code. Basically, Perl scripts call the <TT><FONT FACE="Courier">XSUB</FONT></TT>

routines to get to the C code in the libraries encapsulated by

the <TT><FONT FACE="Courier">XSUB</FONT></TT> functions.

<P>

To ensure that correct data types are mapped between C and Perl

scripts, the XS compiler does a mapping of one C type of variable

to a type in Perl. The mapping is maintained in a file called

<TT><FONT FACE="Courier">typemap</FONT></TT>. When you're looking

for extension files, it's often instructive to see how files are

mapped by using the <TT><FONT FACE="Courier">typemap</FONT></TT>

file in the same directory as the source file. <TT><FONT FACE="Courier">typemap</FONT></TT>

files are covered later in this chapter.

<P>

You may be asking yourself why someone would want to write an

extension in C when Perl is a perfectly good working language.

For one thing, Perl is slow compared to C. Your C compiler can

generate really tight code. All that power does have drawbacks.

Another reason is that you might already have source code written

and working in C, and porting this existing code to Perl would

not make much sense. Also, it's possible to write code that can

be accessed with Perl and C if you write the interfaces to your

core functions correctly.

<H2><A NAME="StepsforCreatinganExtension"><B><FONT SIZE=5 COLOR=#FF0000>Steps

for Creating an Extension</FONT></B></A></H2>

<P>

The best way to show the creation of an extension is by example.

This section steps you through the creation of the <TT><FONT FACE="Courier">futureValue</FONT></TT>

world function for Perl. 

<H3><A NAME="Step1ChangetothePerlDirectory"><B>Step 1: Change

to the Perl Directory</B></A></H3>

<P>

Go to the directory where you installed the Perl distribution.

This is important. Do not try this in any other directory or you'll

get errors.

<H3><A NAME="Step2Runh2sx"><B>Step 2: Run </B><TT><B><FONT SIZE=4 FACE="Courier">h2sx</FONT></B></TT></A>

</H3>

<P>

For Step 2, you have to run the header to extension program <TT><FONT FACE="Courier">h2xs</FONT></TT>.

To obtain a list of the options for this program, use the <TT><FONT FACE="Courier">-h</FONT></TT>

option, as shown here:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">$ <B>h2xs -h<BR>

<BR>

</B>h2xs [-Acfh] [-n module_name] [headerfile [extra_libraries]]

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;-f&nbsp;&nbsp;&nbsp;Force creation of

the extension even if the C header does not exist.<BR>

&nbsp;&nbsp;&nbsp;&nbsp;-n&nbsp;&nbsp;&nbsp;Specify a name to

use for the extension (recommended).<BR>

&nbsp;&nbsp;&nbsp;&nbsp;-c&nbsp;&nbsp;&nbsp;Omit the constant()

function and specialised AUTOLOAD from the XS file.<BR>

&nbsp;&nbsp;&nbsp;&nbsp;-A&nbsp;&nbsp;&nbsp;Omit all autoloading

facilities (implies -c).<BR>

&nbsp;&nbsp;&nbsp;&nbsp;-h&nbsp;&nbsp;&nbsp;Display this help

message<BR>

extra_libraries<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;are any

libraries that might be needed for loading the<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extension,

e.g. -lm would try to link in the math library.</FONT></TT>

</BLOCKQUOTE>

<P>

Run <TT><FONT FACE="Courier">h2XS -n Finance</FONT></TT>. This

creates a directory named <TT><FONT FACE="Courier">Finance</FONT></TT>,

possibly under the subdirectory <TT><FONT FACE="Courier">ext/</FONT></TT>

if it exists in the current working directory. Four files are

created in the <TT><FONT FACE="Courier">Finance</FONT></TT> directory:

<TT><FONT FACE="Courier">MANIFEST</FONT></TT>, <TT><FONT FACE="Courier">Makefile.PL</FONT></TT>,

<TT><FONT FACE="Courier">Finance.pm</FONT></TT>, and <TT><FONT FACE="Courier">Finance.xs</FONT></TT>.

Here's what the output on your terminal will look like:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">$ <B>h2xs -n Finance<BR>

</B>Writing ext/Finance/Finance.pm<BR>

Writing ext/Finance/Finance.xs<BR>

Writing ext/Finance/Makefile.PL</FONT></TT>

</BLOCKQUOTE>

<P>

The <TT><FONT FACE="Courier">MANIFEST</FONT></TT> file in the

<TT><FONT FACE="Courier">ext/Finance</FONT></TT> directory contains

the names of the four files created. You have to change directories

to <TT><FONT FACE="Courier">./ext/Finance</FONT></TT> to be able

to work with these four files. Also, depending on who installed

your Perl distribution, you might have to run as <TT><FONT FACE="Courier">root</FONT></TT>.

<P>

The contents of file <TT><FONT FACE="Courier">Makefile.PL</FONT></TT>

are shown in Listing 27.1.

<HR>

<BLOCKQUOTE>

<B>Listing 27.1. The contents of </B><TT><B><FONT FACE="Courier">Makefile.PL</FONT></B></TT><B>.

<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 use ExtUtils::MakeMaker;<BR>

&nbsp;2 # See lib/ExtUtils/MakeMaker.pm for details of how to

influence<BR>

&nbsp;3 # the contents of the Makefile that is written.<BR>

&nbsp;4 WriteMakefile(<BR>

&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'NAME'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

'Finance',<BR>

&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'VERSION'&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

'0.1',<BR>

&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'LIBS'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

['-lm'],&nbsp;&nbsp;&nbsp;# e.g., '-lm'<BR>

&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'DEFINE'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

'',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# e.g., '-DHAVE_SOMETHING'<BR>

&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Inc'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

'',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# e.g., '-I/usr/include/other'

<BR>

10&nbsp;);</FONT></TT>

</BLOCKQUOTE>

<HR>

<P>

The <TT><FONT FACE="Courier">h2xs</FONT></TT> script also creates

a <TT><FONT FACE="Courier">.pm</FONT></TT> file. The contents

of file <TT><FONT FACE="Courier">Finance.pm</FONT></TT> are shown

in Listing 27.2. The <TT><FONT FACE="Courier">Finance.pm</FONT></TT>

file is where you add your exports and any Perl code.

<HR>

<BLOCKQUOTE>

<B>Listing 27.2. The module file: </B><TT><B><FONT FACE="Courier">Finance.pm</FONT></B></TT><B>.

<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 package Finance;<BR>

&nbsp;2<BR>

&nbsp;3 require Exporter;<BR>

&nbsp;4 require DynaLoader;<BR>

&nbsp;5 require AutoLoader;<BR>

&nbsp;6<BR>

&nbsp;7 @ISA = qw(Exporter DynaLoader);<BR>

&nbsp;8 # Items to export into callers namespace by default. Note:

do not export<BR>

&nbsp;9 # names by default without a very good reason. Use EXPORT_OK

instead.<BR>

10 # Do not simply export all your public functions/methods/constants.

<BR>

11 @EXPORT = qw(<BR>

12<BR>

13 );<BR>

14 sub AUTOLOAD {<BR>

15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# This AUTOLOAD is used to 'autoload'

constants from the constant()<BR>

16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# XS function.&nbsp;&nbsp;If a

constant is not found then control is passed<BR>

17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# to the AUTOLOAD in AutoLoader.

<BR>

18<BR>

19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local($constname);<BR>

20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;($constname = $AUTOLOAD) =~ s/.*:://;

<BR>

21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$val = constant($constname, @_

? $_[0] : 0);<BR>

22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($! != 0) {<BR>

23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($! =~ /Invalid/) {<BR>

24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$AutoLoader::AUTOLOAD

= $AUTOLOAD;<BR>

25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto

&amp;AutoLoader::AUTOLOAD;<BR>

26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<BR>

28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;($pack,$file,$line)

= caller;<BR>

29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;die

&quot;Your vendor has not defined Finance macro<BR>

$constname, used at $file line $line.<BR>

30 &quot;;<BR>

31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eval &quot;sub $AUTOLOAD { $val

}&quot;;<BR>

34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto &amp;$AUTOLOAD;<BR>

35&nbsp;}<BR>

36<BR>

37&nbsp;bootstrap Finance;<BR>

38<BR>

39 # Preloaded methods go here.<BR>

40<BR>

41 # Autoload methods go after _&nbsp;_END_&nbsp;_, and are processed

by the autosplit program.<BR>

42<BR>

43 1;<BR>

44 _&nbsp;_END_&nbsp;_</FONT></TT>

</BLOCKQUOTE>

<HR>

<P>

All scripts which use <TT><FONT FACE="Courier">Finance.pm</FONT></TT>

will now have to tell Perl to use functions in the <TT><FONT FACE="Courier">Finance.pm</FONT></TT>

extension with the following command:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">use Finance;</FONT></TT>

</BLOCKQUOTE>

<P>

When Perl sees this <TT><FONT FACE="Courier">use</FONT></TT> command,

it searches for a <TT><FONT FACE="Courier">Finance.pm</FONT></TT>

file of the same name in the various directories listed in the

<TT><FONT FACE="Courier">@Inc</FONT></TT> array. If it cannot

find the file, Perl stops with an error message.

<P>

The <TT><FONT FACE="Courier">.pm</FONT></TT> file extension generally

requests that the Exporter and Dynamic Loader extensions also

be loaded. You need them for exporting functions and dynamic loading.

Perl uses the <TT><FONT FACE="Courier">@ISA</FONT></TT> array

to get any methods that are not found in the current package.

After this set, the library is loaded as an extension into Perl.

<P>

There are two files to look at in the <TT><FONT FACE="Courier">Finance</FONT></TT>

example we just created. The <TT><FONT FACE="Courier">Finance.xs</FONT></TT>

⌨️ 快捷键说明

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