Categories
Perl XS

Perl niceness, building a XS module that acts like a Perl object.

I have been trying the last days to add Mega.nz support to Peertube-dl, it is not an easy task since Mega.nz implements encryption with AES in the files so the server owner is not able in theory to read the users files. (My opinion is anyway the server admins would be able to get access to those files by simply parsing the server logs.)

I have not success yet, because the lack of good Perl libraries and the bad Perl is for parsing binary data and then I thought, why not try to use XS to solve this problem as I did before with the Javascript interpreter need for Youtube?

So this I am trying, and in the process I did a little improvement in my way to write XS thanks to the learn about how to use typemaps to build more ideomatic for both Perl and C XS modules.

Let’s start the house by the roof, would not be great being able to write a XS module like this:

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stdio.h>

typedef struct helper {
    int value;
} * Peertube_DL_Mega_Helper;

MODULE = Peertube::DL::Mega::Helper  PACKAGE = Peertube::DL::Mega::Helper
PROTOTYPES: DISABLE

Peertube_DL_Mega_Helper
new(class, value)
    char *class
    int value
    CODE:
        RETVAL = malloc(sizeof (struct helper));
        RETVAL->value = value;
    OUTPUT:
        RETVAL

void
print(self)
    Peertube_DL_Mega_Helper self
    CODE:
        printf("%d\n", self->value);

void
DESTROY(self)
    Peertube_DL_Mega_Helper self
    CODE:
        free(self);

This code can be achieved with the help of the file typemap, with the help of https://perldoc.perl.org/perlxstypemap I discovered that, and the following typemap will look familiar to anybody which have read that document.

TYPEMAP
    Peertube_DL_Mega_Helper T_PTROBJ_SPECIAL

INPUT
T_PTROBJ_SPECIAL
    if (sv_derived_from($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")){
        IV tmp = SvIV((SV*)SvRV($arg));
        $var = INT2PTR($type, tmp);
    } else {
        croak(\"$var is not of type ${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\");
    }

OUTPUT
T_PTROBJ_SPECIAL
    sv_setref_pv($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\",
           (void*)$var);

Of course some more additions will be needed to make this code run, like the clasical xsloader Perl module and some lines in the Makefile.PL which is out of scope in this document.

We will be able to run this code like this and check it works:

perl -MPeertube::DL::Mega::Helper -e 'Peertube::DL::Mega::Helper->new(3)->print';

It should print 3.

It is true XS is scaring because strange subroutines and magical variable names and tons of rare sections difficult to understand on the first read of the docs, but this kind of sugar makes my day, it is a shame there aren’t much XS articles and Stackoverflow responses because makes the language slower to learn.

By sergiotarxz

I am a software developer with high interest on free software.

Leave a Reply

Your email address will not be published. Required fields are marked *