Get a hash value using XS

This is an example of using Perl's XS extension "language" to make a simple extension to print out a hash value.

This is the Perl module, which is called GetHashValue.pm:

package GetHashValue;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = 'get_hash_value';
require XSLoader;
our $VERSION = '0.001';
XSLoader::load('GetHashValue', $VERSION);
1;

(download)

This is the XS part of the module, GetHashValue.xs, which goes in the top directory:

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "get-hash-value.h"

MODULE=GetHashValue PACKAGE=GetHashValue

PROTOTYPES: ENABLE

void get_hash_value (hash)
    HV * hash
    CODE:
    get_hash_value (hash);

(download)

This is a C file, get-hash-value.c which contains the working bits of our program. This is in its own file.

#include <stdio.h>

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

#include "get-hash-value.h"

void get_hash_value (HV * hash)
{
    const char * key = "test-key";
    SV * key_sv;

    key_sv = newSVpv (key, strlen (key));
    if (hv_exists_ent (hash, key_sv, 0)) {
        HE * he;
        SV * val;
        char * val_pv;
        int val_length;
        int val_iv;
        printf ("The key for '%s' seems to exist.\n", key);
        he = hv_fetch_ent (hash, key_sv, 0, 0);
        val = HeVAL (he);
        val_pv = SvPV (val, val_length);
        printf ("As a string, its value is '%s' (length %d).\n",
                val_pv, val_length);
        if (SvIOK (val)) {
            val_iv = SvIV (val);
            printf ("As a number, its value is '%d'.\n",
                    val_iv);
        }
        else {
            printf ("Perl doesn't think it's a number.\n");
        }
    }
    else {
        printf ("The key for '%s' doesn't seem to exist.\n", key);
    }
}

(download)

You also need a header file so the XS file knows what's in the C file. The following one is automatically generated by Cfunctions.

/* This is a Cfunctions (version 0.27) generated header file.
   Cfunctions is a free program for extracting headers from C files.
   Get Cfunctions from `http://cfunctions.sourceforge.net/'. */

/* This file was generated with:
`cfunctions -i -c -n get-hash-value.c' */
#ifndef CFH_GET_HASH_VALUE_H
#define CFH_GET_HASH_VALUE_H

/* From `get-hash-value.c': */

#line 6 "get-hash-value.c"
void get_hash_value (HV * hash );

#endif /* CFH_GET_HASH_VALUE_H */

(download)

You also need a file called Makefile.PL in order to compile this. As usual, you do

$ perl Makefile.PL
$ make

With the test program as below you don't need to bother with "make install". There is no test so "make test" won't work!

use strict;
use warnings;
use ExtUtils::MakeMaker;

WriteMakefile (
    NAME         => 'GetHashValue',
    VERSION      => '0.001',
    OBJECT       => 'GetHashValue.o get-hash-value.o',
);

# Include the dependencies in the header file.

sub MY::postamble
{
    return <<EOF;
GetHashValue.o: get-hash-value.h

get-hash-value.o: get-hash-value.h
EOF
}

(download)

The following is a test program.

#!/home/ben/software/install/bin/perl
use warnings;
use strict;
use lib 'blib/arch';
use lib 'blib/lib';
use GetHashValue;
get_hash_value ({bonkers => 1});
get_hash_value ({bonkers => 1, 'test-key' => 1});
get_hash_value ({bonkers => 1, 'test-key' => "A million", x => 'y'});
get_hash_value ({});

(download)

The output should look something like this (hopefully):

The key for 'test-key' doesn't seem to exist.
The key for 'test-key' seems to exist.
As a string, its value is '1' (length 1).
As a number, its value is '1'.
The key for 'test-key' seems to exist.
As a string, its value is 'A million' (length 9).
Perl doesn't think it's a number.
The key for 'test-key' doesn't seem to exist.

Copyright © Ben Bullock 2009-2023. All rights reserved. For comments, questions, and corrections, please email Ben Bullock (benkasminbullock@gmail.com) or use the discussion group at Google Groups. / Privacy / Disclaimer