19.2. Other Languages
Occasionally you may need to use code resources that are not written in Perl. Most often this will be C code, but it might also be C++, Java, Python, Ruby, Tcl, Scheme, AWK, or even Basic. The CPAN provides interface tools for hooking all of these languages up to a Perl program, but most of those tools are very challenging to use correctly. By far the most frequently used is xsubpp, a compiler for Perl's own "XS" interface description language (see the perlxstut manpage[*]).
Hooking Perl to C using XS requires you to write a shell .pm module to bootstrap an object file that has been compiled from C code, which was in turn generated by xsubpp from a .xs source file containing pseudo-C annotated with an XS interface description. If that sounds horribly complicated, then you have achieved an accurate understanding of the use of xsubpp. Example 19-1 shows just how much work is involved in even a very simple example. Example 19-1. Creating a fast C-based rounding subroutine using XS> cat Round.pm package Round; use strict; use warnings; use base qw( Exporter DynaLoader ); our $VERSION = '0.01'; @EXPORT = qw( round ); bootstrap Round $VERSION; 1; _ _END_ _ > cat rounded.pl use Round; use IO::Prompt; while (my $num = prompt -num => 'Enter a number: ') { print rounded($num), "\n"; } > cat Round.xs #include "EXTERN.h" #include "perl.h" #include "XSUB.h" MODULE = Round PACKAGE = Round int rounded(arg) double arg CODE: int res; /* Round towards zero... */ if (arg > 0.0) { res = floor(arg + 0.5); } else if (arg < 0.0) { res = ceil(arg - 0.5); } else { res = 0; } OUTPUT: res > cat Makefile.PL use ExtUtils::MakeMaker; WriteMakefile( NAME => 'Round', VERSION_FROM => 'Round.pm', LIBS => ['-lm'], ); > perl Makefile.PL Checking if your kit is complete... Looks good Writing Makefile for Mytest > make install umask 0 && cp Mytest.pm ./blib/Mytest.pm perl xsubpp -typemap typemap Mytest.xs >Mytest.tc && mv Mytest.tc Mytest.c Please specify prototyping behavior for Mytest.xs (see perlxs man) cc -c Mytest.c Running Mkbootstrap for Mytest ( ) chmod 644 Mytest.bs LD_RUN_PATH="" ld -o ./blib/auto/Mytest/Mytest.sl -b M ytest.o chmod 755 ./blib/auto/Mytest/Mytest.sl cp Mytest.bs ./blib/auto/Mytest/Mytest.bs chmod 644 ./blib/PA-RISC1.1/auto/Mytest/Mytest.bs Manifying ./blib/man3/Mytest.3 It's probably not surprising that most Perl programmers recoil from that approach. A much less demanding alternative is to use the Inline module, which allows you to include standard C code directly in your Perl application. Example 19-2 shows the rounded.pl application from Example 19-1, but now reimplemented using Inline. Example 19-2. Creating a fast C-based rounding subroutine using Inline::C > cat rounded.pl use Inline C => q{ int rounded(double arg) { Notice that, in this second version, there's no need for a separate .xs file, or a .pm wrapper module, or any explicit translation process, or compilation step. You just type your C code into your Perl source, as part of the use Inline C statement. Then, when rounded.pl is executed, Inline's import( ) subroutine parses the C code, builds a suitable XS representation, compiles it with the local C compiler, and loads the resulting object file back into the running process. Of course, if that happened every time you ran the program, any performance benefit you might have gained by writing rounded( ) in C would clearly be more than overwhelmed by the costs of continually reparsing and recompiling. Fortunately, Inline caches any object files it builds and reparses and recompiles the original C source code only when that code actually changes. The very first time rounded.pl was run there would be a noticeable compilation delay, but thereafter the application would start almost instantly and reap the full performance benefits of its partial C implementation. The second great advantage of using Inline is that there are other CPAN modules that allow it to also handle inlined C++, Java, Python, Ruby, Tcl, Scheme, AWK, bc, Basic, Parrot, and assembler[*]. You can even mix and match multiple languages within the same Perl program. For example, you might implement the number-crunching components in C, the GUI in Java, and the embedded artificial intelligence in Scheme.
|