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:
- No need to modify Makefile.PL
- No need to modify the name of the file SomeModule.xs
- Only one XS file called SomeModule.xs is OK
- 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.