View on
MetaCPAN is shutting down
For details read Perl NOC. After June 25th this page will redirect to
Salvador Fandiño García > Module-CAPIMaker-0.01 > Module::CAPIMaker



Annotate this POD

View/Report Bugs
Module Version: 0.01   Source  


Module::CAPIMaker - Provide a C API for your XS modules


  perl -MModule::CAPIMaker -e make_c_api


If you are the author of a Perl module written using XS. Using Module::CAPIMaker you will be able to provide your module users with an easy and efficient way to access its functionality directly from their own XS modules.


The exporting/importing of the functions provided through the C API is completely handled by the support files generated by Module::CAPIMaker, and not the author of the module providing the API, neither the authors of the client modules need really to know how it works but on the other hand it does not harm to understand it and anyway it will probably easy the understanding of the module usage. So, read on :-) ..

Suppose that we have one module Foo::XS Foo::XS providing a C API with the help of Module::CAPIMaker and another module Bar that uses that API.

When Foo::XS is loaded, the addresses of the functions available through the C API are published on the global hash %Foo::XS::C_API.

When Bar loads, first, it ensures that Foo::XS is loaded (loading it if required) and checks that the versions of the C API supported by the version of Foo::XS loaded include the version required. Then, it copies the pointers on the %Foo::XS::C_API hash to C static storage where they can be efficiently accessed without performing a hash look-up every time.

Finally calls on Bar to the C functions from Foo::XS are transparently routed through these pointers with the help of some wrapping macros.


The C API is defined in a file named c_api.decl. This file may contain the prototypes of the functions that will be available through the C API and several configuration settings.

From this file, Module::CAPIMaker generates two sets of files, one set contains the files that are used by the module providing the C API in order to support it. The other set is to be used by client modules.

They are as follows:

C API provider support files

On the C API provider side, a file named c_api.h is generated. It defines the initialization function that populates the %C_API hash.

Client support files

There are two main files to be used by client modules, one is perl_${c_module_name}.c containing the definition of the client side C API initialization function.

The second file is perl_${c_module_name}.h containing the prototypes of the functions made available through the C API and a set of macros to easy their usage.

${c_module_name} is the module name lower-cased and with every non-alphanumeric sequence replaced by a underscore in order to make in C friendly. For instance, Foo::XS becomes foo_xs and the files generated are perl_foo_xs.c and perl_foo_xs.h.

A sample/skeleton Sample.xs file is also generated.

The client files go into the directory c_api_client where you may also like to place additional files as for instance a typemap file.


The C API is defined through the file c_api.decl.

Two types of entries can be included in this file: function prototypes and configuration settings.

Function declarations

Function declarations are identical to those you will use in a C header file (without the semicolon at the end). In example:

  int foo(double)
  char *bar(void)

Functions that use the THX macros are also accepted:

  SV *make_object(pTHX_ double *)

You have to use the prototype variant (pTHX or pTHX_) and Module::CAPIMaker will replace it automatically by the correct variant of the macro depending of the usage.

Configuration settings

Configuration settings are of the form key=value where key must match /^\w+$/ and value can be anything. For instance

   module_name = Foo::XS
   author = Valentine Michael Smith

A backslash at the end of the line indicates that the following line is a continuation of the current one:

   some_words = bicycle automobile \
                house duck

Here-docs can also be used:

   some_more_words = <<END
   car pool tree
   disc book

The following configuration settings are currently supported by the module:


Perl name of the module, for instance, Foo::XS.

c_module_name = foo_bar

C-friendly name of the module, for instance foo_xs


Version of the Perl module. This variable should actually be set from the Makefile.PL script and is not used internally by the C API support functions. It just appears on the comments of the generated files.

author = Valentine M. Smith <>

Name of the module author, to be included on the headers of the generated files.


In order to support evolution of the C API a min/max version approach is used.

The min_version/max_version numbers are made available through the %C_API hash. When the client module loads, it checks that the version it requires lays between these two numbers or otherwise croaks with an error.

By default required_version is made equal to max_version.


The directory where the client support files are placed. By default c_api_client.


Name of the client support header file (i.e. perl_foo_xs.h).


Name of the client C file providing the function to initialize the client side of the C API (i.e. perl_foo_xs.c).


Name of the support file used on the C API provider side. Its default value is c_api.h.


Name of the macro used to avoid multiple loading of the definitions inside ${module_h_filename}.

It defaults to uc("${c_module_name}_H_INCLUDED"). For instance PERL_FOO_XS_H_INCLUDED.


Name of the macro used to avoid multiple loading of the definitions on the header file c_api.h. It defaults to C_API_H_INCLUDED.


It's possible to add a prefix to the name of the functions exported through the C API in the client side.

For instance, if the function bar() is exported from the module Foo::XS, setting export_prefix=foo_ will make that function available on the client module as foo_bar().


The text in this variable is placed inside the file ${module_c_filename} at some early point. It can be used to inject typedefs and other definitions needed to make the file compile.


The text inside this variable is placed at the end of the file ${module_c_filename}.


The text inside this variable is placed inside the file ${module_h_filename} at some early point.


The text inside this variable is placed at the end of the file ${module_h_filename}.


The name of the file with the definition of the C API. Defaults to c_api.decl.

Obviously this setting can only be set from the command line!


Internally the module uses Text::Template to generate the support files with a set of default templates. For maximum customizability a different set of templates can be used.

See "Customizing the C API generation process".


Once your c_api.decl file is ready use Module::CAPIMaker to generate the C API running the companion script make_perl_module_c_api. This script also accept a list of configuration setting from the command line. For instance:

  make_perl_module_c_api module_name=Foo::XS \
      author="Valentine Michael Smith"

If you want to do it from some Perl script, you can also use the make_c_api sub exported by this module.


In order to initialize the C API from the module supporting it you have to perform the following two changes on your XS file:

  1. Include c_api.h.
  2. Call the macro INIT_C_API from the BOOT section.

For instance,

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

  /* your C code goes here */

  #include "c_api.h"

  MODULE = Foo::XS              PACKAGE = Foo::XS


  /* your XS function declarations go here */


In order to get the C API interface files regenerated every time the file c_api.decl is changed, add the following lines at the end of your Makefile.PL script.

  package MY;

  sub postamble {
      my $self = shift;
      my $author = $self->{AUTHOR};
      $author = join(', ', @$author) if ref $author;
      $author =~ s/'/'\''/g;

      return <<MAKE_FRAG

  c_api.h: c_api.decl
  \tmake_perl_module_c_api module_name=\$(NAME) module_version=\$(VERSION) author='$author'
  sub init_dirscan {
      my $self = shift;
      push @{$self->{H}}, 'c_api.h' unless grep $_ eq 'c_api.h', @{$self->{H}};

You may also like to include the generated files into the file MANIFEST in order to not require your module users to also have Module::CAPIMaker installed.


The module Module::CAPIMaker exports the subroutine make_c_api when loaded. This sub parses module settings from @ARGV and the file a_api.decl and performs the generation of the C API support files.


In order to use functions provided by a XS module though a C API generated by Module::CAPIMaker, you have to perform the following steps:

  1. Copy the files from the c_api_client directory into your module directory.
  2. On your Makefile.PL script, tell ExtUtils::MakeMaker to compile and link the C file just copied. That can be attained adding OBJECT => '$(O_FILES)' arguments to the WriteMakefile call:
                    OBJECT        => '$(O_FILES)',
  3. Include the header file provided from all the compilation units (usually .c and .xs files) that want to use the functions available through the C API.
  4. Initialize the client side of the C API from the BOOT section of your XS module calling the load-or-croak macro. For instance:
      #include "EXTERN.h"
      #include "perl.h"
      #include "XSUB.h"
      #include "ppport.h"
      #include "perl_foo_xs.h"
      MODULE=Bar    PACKAGE=Bar


Internally, the module uses Text::Template to generate the support files.

In order to allow for maximum customizability, the set of templates used can be changed.

As an example of a module using a customized set of templates see Math::Int64.

The default set of templates is embedded inside the sub-modules under Module::CAPIMaker::Template, you can use them as an starting point.

Finally, if you find the module limiting in some way don't hesitate to contact me explaining your issued. I originally wrote Module::CAPIMaker to solve my particular problems but I would gladly expand it to make it cover a wider range of problems.


Math::Int128, Math::Int64, Tie::Array::Packed are modules providing or using (or both) a C API created with the help of Module::CAPIMaker.


Copyright (C) 2012 by Salvador Fandiño, <>.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.12.4 or, at your option, any later version of Perl 5 you may have available.

syntax highlighting: