[Thousand-Oaks-pm] Responding to Barry's question on basing a module on C code.

David Oswald daoswald at gmail.com
Thu Apr 12 19:31:11 PDT 2012


Last night Barry asked the good question of how one might embed C code
in a Perl module.  I wanted to just respond briefly here.

There are several ways to do it, as you might expect.

The first option (and probably most difficult) is to learn the Perl XS
glue language and write your module in XS code, which gets translated
by ExtUtils::ParseXS to C.  Details for this method are found in
perlxstut, perlxs, perlapi, perlcall, perlguts, and ExtUtils::ParseXS
POD.  A few brave souls do it this way.  I don't recommend it because
there are easier ways.


The next option is much easier.  I know several prolific CPAN authors
who use this technique.  Write a program using Inline::C, and include
the C code inline in the Perl script as discussed in the Inline::C and
Inline::C-Cookbook documentation.  You will probably still need to
read perlguts at minimum, as well as the POD for Inline, Inline::C,
and Inline::C-Cookbook.  But here's the cool part: If you use the "use
Inline => 'NoClean'; option, then after your script runs you will be
left with an XS file in its _Inline build directory.  Now start an XS
module with 'h2xs -XAn My::Module', and then copy and paste the code
contained in the _Inline/*.xs file to the end of the XS file generated
by h2xs.  Presto, no need to specifically learn the XS glue language;
Inline::C writes it for you.

For a module intended for broad use (and presumably maximum
portability), that's the best method.  As an author, you use
Inline::C, but by copying and pasting the XS code it generates into
your new module, you literally shed the Inline::C dependency for your
users.


The third option is the easiest of all, but retains the Inline::C
dependency.  Go ahead and start your module with Module::Starter.  In
your module's code, "use Inline C => 'DATA';", and then place your C
code after the __DATA__ segment in the module.  Within your
Makefile.PL, replace ExtUtils::MakeMaker with Inline::MakeMaker.  List
ExtUtils::MakeMaker version 6.52, and Inline::MakeMaker version 0.50
as CONFIGURE_REQUIRES dependencies, and Inline and Inline::C version
0.50 as BUILD_REQUIRES dependencies in Makefile.PL.  Now when your
module is installed on a target system, your C extension code will be
compiled once, upon installation.  Subsequent runs using the module
will not incur the compilation penalty, just the initial install.  The
biggest downside to this is that it will pull in Inline and Inline::C
on the target system.  Those modules are highly portable, but their
installation takes some time (the test suite is slow).

sisyphus at cpan.org also has an Inline::C2XS and Inline::CPP2XS set of
modules that sort of automate the second option mentioned above.  They
work quite well.

As a proof-of-concept for the third option (the Inline dependency
option), see Math::Prime::FastSieve, which uses Inline::CPP as a
module dependency to allow the module to be built around C++ code.

So to summarize:

1: Write the XS code yourself. -- Difficulty: Hard to Diabolical.
2: Let Inline::C write the XS code for you, and then use Inline::C2XS
reappropriate the XS code into your new module.  -- No strange
dependencies for target users. -- Difficulty: Medium-hard.
3: Use Inline::C as a module dependency. -- User will be forced to
pull in the Inline::C dependency (it's pretty easy but takes time).
Runtime is just as efficient as pure XS. -- Difficulty: Easy to
Medium.


Dave

-- 

David Oswald
daoswald at gmail.com


More information about the Thousand-Oaks-pm mailing list