1. Perl
  2. XS
  3. here

Easy way to implement XS using multiple modules

When I tried to make a module using XS, I suddenly had a problem when dividing it into multiple modules. For example, if you want to implement XS with both SomeModule and SomeModule::Util. I was investigating the method, but I found the implementation method to be quite complicated and difficult.

I tried various things, but the next method seemed to be easy, so I will introduce it. The advantages of this method are:

  1. No need to modify Makefile.PL
  2. No need to modify the name of the file SomeModule.xs
  3. Only one XS file called SomeModule.xs is OK
  4. The standard tool h2xs is fine

Create a module with h2xs

First, create a module for XS with h2xs.

h2xs -A -n SomeModule

This will create a directory called "SomeModule". The following files and directories will be created.

Changes
lib/Makefile.PL
MANIFEST
ppport.h
README
SomeModule.xs
t/</pre>

<h4>XS file description</h4>

I will create an XS file. Let's add a function called foo that displays "foo" to SomeModule, and a function called bar that displays "bar" to SomeModule::Util.

First of all, when you open the XS file, you should see something like the following.

<pre>
# include "EXTERN.h"
# include "perl.h"
# include "XSUB.h"

# include "ppport.h"


MODULE = SomeModule PACKAGE = SomeModule

The first thing to remember is that the "MODULE = SomeModule PACKAGE = SomeModule" section should be at the bottom. If you do not leave this part at the end, the XS will fail to load.

Let's write it. Add "MODULE = SomeModule::Util PACKAGE = SomeModule::Util". Then define bar in XS. Also, define foo in the section "MODULE = SomeModule PACKAGE = SomeModule".

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

# include "ppport.h"

MODULE = SomeModule::Util PACKAGE = SomeModule::Util

void
bar (...)
  PPCODE:
{
  PerlIO_printf(PerlIO_stdout (), "bar\n");
  XSRETURN (0);
}

MODULE = SomeModule PACKAGE = SomeModule

void
foo (...)
  PPCODE:
{
  PerlIO_printf(PerlIO_stdout (), "foo\n");
  XSRETURN (0);
}

Creating a module

At this point, all you have to do is create SomeModule and SomeModule::Util.

SomeModule source code

You can leave the source code for SomeModule.pm as it is. I organized it a little and made it as follows.

package SomeModule;

use strict;
use warnings;

our $VERSION = '0.01';

require XSLoader;
XSLoader::load ('SomeModule', $VERSION);

1;

SomeModule::Util source code

Let's also create SomeModule::Util::bar. Save this in "lib/SomeModule/Util.pm". This is an almost empty file with only the package name declared.

package SomeModule::Util;

1;

Test script

Create a test script. This should be in the same directory where the XS files are located.

use strict;
use warnings;

use SomeModule;
use SomeModule::Util;

SomeModule::foo ();
SomeModule::Util::bar ();

Compile and run

Let's compile and run it.

perl Makefile.PL
make
perl -Mblib test.pl

If the output is as follows, it is successful.

foo
bar

Writing XS in multiple modules doesn't seem to be that difficult.

Related Informatrion