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

📄 ch27.htm

📁 《Perl 5 Unreleased》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
If your Perl distribution was installed by <TT><FONT FACE="Courier">root</FONT></TT>,

you may not have permission to overwrite some files. It won't

hurt to try.

<P>

If you do not get any errors, proceed.

<P>

Run the makefile on your newly created <TT><FONT FACE="Courier">Makefile</FONT></TT>.

The following output should be pretty close to what you see:

<BLOCKQUOTE>

<TT><FONT FACE="Courier"># <B>make<BR>

<BR>

</B>umask 0 &amp;&amp; cp Finance.pm ../../lib/Finance.pm<BR>

../../perl -I../../lib -I../../lib ../../lib/ExtUtils/xsubpp<BR>

-typemap ../../lib/ExtUtils/typemap Finance.XS<BR>

&gt;Finance.tc &amp;&amp; mv Finance.tc Finance.c<BR>

cc -c -D_&nbsp;_USE_BSD_SIGNAL -Dbool=char -DHAS_BOOL<BR>

-O2&nbsp;&nbsp;&nbsp;&nbsp;-DVERSION=\&quot;0.1\&quot; -fpic -I../..&nbsp;&nbsp;Finance.c

<BR>

Running Mkbootstrap for Finance ()<BR>

chmod 644 Finance.bs<BR>

LD_RUN_PATH=&quot;&quot; cc -o ../../lib/auto/Finance/Finance.so

-shared<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-L/usr/local/lib Finance.o<BR>

chmod 755 ../../lib/auto/Finance/Finance.so<BR>

cp Finance.bs ../../lib/auto/Finance/Finance.bs<BR>

chmod 644 ../../lib/auto/Finance/Finance.bs</FONT></TT>

</BLOCKQUOTE>

<P>

Wait! Before you execute this gem of a script shown above, look

at the output in Listing 27.6. The shared version of <TT><FONT FACE="Courier">Finance.so</FONT></TT>

is in the directory <TT><FONT FACE="Courier">../../lib/auto/Finance/Finance.so</FONT></TT>.

It is important that you copy <TT><FONT FACE="Courier">Finance.so</FONT></TT>

to your <TT><FONT FACE="Courier">@Inc</FONT></TT> path. It's important

at this point to either modify the <TT><FONT FACE="Courier">@Inc</FONT></TT>

array in your scripts that use <TT><FONT FACE="Courier">Finance.pm</FONT></TT>

or, by default, point to a known test location where this <TT><FONT FACE="Courier">.so</FONT></TT>

file will reside. Perl will search the directories listed in <TT><FONT FACE="Courier">@Inc</FONT></TT>

to load the extension module.

<H3><A NAME="Step5TestYourExtensionModule"><B>Step 5: Test Your

Extension Module</B></A></H3>

<P>

Now, in the <TT><FONT FACE="Courier">Test1</FONT></TT> directory,

create the test script shown in Listing 27.5 and name it <TT><FONT FACE="Courier">t.pl</FONT></TT>.

<HR>

<BLOCKQUOTE>

<B>Listing 27.5. The test program.<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 #!/usr/bin/perl<BR>

&nbsp;2<BR>

&nbsp;3 use Finance;<BR>

&nbsp;4<BR>

&nbsp;5 Finance::Gordon(50,4,2);<BR>

&nbsp;6 print &quot;\n&quot;;<BR>

&nbsp;7<BR>

&nbsp;8 #<BR>

&nbsp;9 #<BR>

10 #<BR>

11 $pv = 1000.0;<BR>

12 $time = 10 * 12;<BR>

13 $rate = 0.05 / 12;<BR>

14 $fv = Finance::futureValue($pv,$rate,$time);<BR>

15 printf &quot;\n Future Value of %f after %f periods accruing

interest &quot;,<BR>

16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$pv,

$rate;<BR>

17 printf &quot;\n for %f months will be r %f \n&quot;,<BR>

18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$time,

$fv;<BR>

19<BR>

20 printf &quot;\n Let us go backward and see if we get the same

numbers&quot;;<BR>

21 $pvBack = Finance::presentValue($fv,$rate,$time);<BR>

22 printf &quot;\n Present Value &quot;, $pvBack;<BR>

23<BR>

24 printf &quot;\n Difference = %f&quot;, ($pv - $pvBack);<BR>

25<BR>

26 printf &quot;\n ------- see any difference? --------- \n&quot;

;</FONT></TT>

</BLOCKQUOTE>

<HR>

<P>

Notice that <TT><FONT FACE="Courier">Finance::Gordon</FONT></TT>

is used to explicitly call the <TT><FONT FACE="Courier">Gordon

Growth Model</FONT></TT> function (see line 5). Look up the formula

in your finance textbook if you don't believe me. It would be

cumbersome to keep typing in <TT><FONT FACE="Courier">Finance::</FONT></TT>

to all your functions. Add the declaration to the <TT><FONT FACE="Courier">@EXPORT</FONT></TT>

array in <TT><FONT FACE="Courier">Finance.pm</FONT></TT> and remake.

Now you can use the function <TT><FONT FACE="Courier">Gordon</FONT></TT>

by itself. The <TT><FONT FACE="Courier">@EXPORT</FONT></TT> array

in the <TT><FONT FACE="Courier">.pm</FONT></TT> file tells Perl

which of the extension's routines should be placed in the calling

package's own name space.

<H3><A NAME="FinalConsiderations"><B>Final Considerations</B></A>

</H3>

<P>

There are some things you should be aware of before you export

everything in your module. Sure, it saves you typing and makes

the code easier to read by not having all those <TT><FONT FACE="Courier">Finance::</FONT></TT>

prefixes everywhere. However, what about the same function name

residing in both the main and the modules? In this case, the function

in the main may prevail. Why create an ambiguity when the choice

of a good name for a function will suffice? Also, it's not a good

idea to export every function in your extension. After all, the

idea behind the extension is to hide some of the functionality

and intricacies in the extension from the application that is

using this extension module.

<P>

Most of the time you do not want to export the names of your extension's

subroutines because they might accidentally clash with other modules'

subroutines from other extensions or from the calling program

itself.

<H2><A NAME="ThexsubppCompiler"><B><FONT SIZE=5 COLOR=#FF0000>The

</FONT></B><TT><B><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">xsubpp</FONT></B></TT><B><FONT SIZE=5 COLOR=#FF0000>

Compiler</FONT></B></A></H2>

<P>

If you examine the makefile for your extension, you'll see a call

to a program called <TT><FONT FACE="Courier">xsubpp</FONT></TT>.

This is a preprocessor compiler for XS code.

<P>

The compiler <TT><FONT FACE="Courier">xsubpp</FONT></TT> takes

the XS code in the <TT><FONT FACE="Courier">.xs</FONT></TT> file,

converts it into C code, and places it in a file whose suffix

is <TT><FONT FACE="Courier">.c</FONT></TT>. The C code created

makes heavy use of the C functions within Perl.<P>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR VALIGN=TOP><TD ><B>Tip</B></TD></TR>

<TR VALIGN=TOP><TD >

<BLOCKQUOTE>

Make sure the <TT><FONT FACE="Courier">xsubpp</FONT></TT> compiler is in your path and that the first line in the file points to <TT><FONT FACE="Courier">/usr/bin/perl</FONT></TT> and not to <TT><FONT FACE="Courier">.miniperl</FONT></TT> (if you did not 

install <TT><FONT FACE="Courier">miniperl</FONT></TT>).

</BLOCKQUOTE>



</TD></TR>

</TABLE></CENTER>

<P>

<P>

An <TT><FONT FACE="Courier">XSUB</FONT></TT> function is just

like a C function in that it takes arguments and returns one or

more single values (if not declared void). Values may also be

returned via pointers to arguments passed to the function.

<P>

Now move on to something a little bit more exotic and create a

function that takes arguments and returns something. This function

calculates and returns the Julian day given a calendar day. The

Julian day calculation is very important in astronomical calculations

since it's a reference counter from all the days since January

1, 4713 B.C. and was founded by the French scholar Joseph Scaliger

(1540-1609) in 1583 A.D. The formula for calculating the Julian

day is given in forms in just as many astronomical texts. One

version of this formula is:

<P>

<BLOCKQUOTE>

<I>Julian Day = 367 * YEAR - 7 * (YEAR + (M + 9)/12)4 +<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(275

* M / 9) + 1721013.5;</I>

</BLOCKQUOTE>

<P>

Don't try to shorten the formula by reducing it to an algebraic

equivalent since the formula relies on dropping bits off the right

side of the decimal point. One such way of implementing this formula

is the function for calculating the Julian day, as shown in Listing

27.6.

<HR>

<BLOCKQUOTE>

<B>Listing 27.6. The </B><TT><B><FONT FACE="Courier">Julian.c</FONT></B></TT><B>

file.<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 #include &lt;math.h&gt;<BR>

&nbsp;2<BR>

&nbsp;3 long JulianDay( int month, int day, int year)<BR>

&nbsp;4 {<BR>

&nbsp;5 double t1, t2;&nbsp;&nbsp;long jd;<BR>

&nbsp;6 t1 = 7 * floor((year + floor(month * 9)/12)/4);<BR>

&nbsp;7 t2 = floor(275 * month / 9);<BR>

&nbsp;8 jd = (long) (floor(367 * year - t1 + t2 + day + 1721013.5));

<BR>

&nbsp;9&nbsp;&nbsp;return(jd);<BR>

10 }<BR>

11 /* SAMPLE USAGE<BR>

12 main(int argc, char *argv[])<BR>

13 {<BR>

14 long day1, day2;<BR>

15 day1 = JulianDay(7,21,1962);<BR>

16 day2 = JulianDay(2,2,1996);<BR>

17 printf(&quot;\n Thou are only %d days old&quot;, day2 - day1);

<BR>

18 }<BR>

19 */</FONT></TT>

</BLOCKQUOTE>

<HR>

<P>

Run <TT><FONT FACE="Courier">h2xs -A -n Julian</FONT></TT> as

before to get the Julian module started. This creates the <TT><FONT FACE="Courier">ext/Julian</FONT></TT>

directory with the necessary files. This time, however, you'll

be adding a lot more code into the functions in <TT><FONT FACE="Courier">Julian.xs</FONT></TT><FONT FACE="AGaramond Bold">,

</FONT>as shown in Listing 27.7.

<HR>

<BLOCKQUOTE>

<B>Listing 27.7. Adding functions to </B><TT><B><FONT FACE="Courier">Julian.xs</FONT></B></TT><B>.

<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 #ifdef _&nbsp;_cplusplus<BR>

&nbsp;2 extern &quot;C&quot; {<BR>

&nbsp;3 #endif<BR>

&nbsp;4 #include &quot;EXTERN.h&quot;<BR>

&nbsp;5 #include &quot;perl.h&quot;<BR>

&nbsp;6 #include &quot;XSUB.h&quot;<BR>

&nbsp;7 #ifdef _&nbsp;_cplusplus<BR>

&nbsp;8 }<BR>

&nbsp;9 #endif<BR>

10<BR>

11 MODULE = Julian&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PACKAGE

= Julian<BR>

12<BR>

13 #include &lt;math.h&gt;<BR>

14<BR>

15 long<BR>

16 JulianDay( month, day, year)<BR>

17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int month<BR>

18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int day<BR>

19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long year<BR>

20<BR>

21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CODE:<BR>

22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long

jul;<BR>

23 double t1, t2;<BR>

24 t1 = 7 * floor((year + floor(month * 9)/12)/4);<BR>

25 t2 = floor(275 * month / 9);<BR>

26 jul = (long) (floor(367 * year - t1 + t2 + day + 1721013.5));

<BR>

27<BR>

28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RETVAL

= jul;<BR>

30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OUTPUT:<BR>

31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RETVAL</FONT></TT>

</BLOCKQUOTE>

<HR>

<P>

Note that each line containing the arguments after the declaration

of <TT><FONT FACE="Courier">JulianDay</FONT></TT> is indented

one tab. It is not necessary to have a tab between the type of

variable and the name of the variable. Also note that that there

is no semicolon following the declaration of each variable.

<P>

Edit the file <TT><FONT FACE="Courier">Makefile.PL</FONT></TT>

so that the corresponding line looks like this:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">'LIBS'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;

['-lm'],&nbsp;&nbsp;&nbsp;# e.g., '-lm'</FONT></TT>

</BLOCKQUOTE>

<P>

Notice that an extra library to link in has been specified in

this case, the math library, <TT><FONT FACE="Courier">libm</FONT></TT>.

You'll learn later in this chapter how to write <TT><FONT FACE="Courier">XSUB</FONT></TT>s

that can call every routine in a library.

<P>

Generate the <TT><FONT FACE="Courier">makefile</FONT></TT> and

run <TT><FONT FACE="Courier">make</FONT></TT>. A test script for

running this program is shown in List-ing 27.8.

<HR>

<BLOCKQUOTE>

<B>Listing 27.8. Testing the </B><TT><B><FONT FACE="Courier">Julian

Day</FONT></B></TT><B> module.<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 #!/usr/bin/perl<BR>

&nbsp;2<BR>

&nbsp;3 use Julian;<BR>

&nbsp;4<BR>

⌨️ 快捷键说明

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