The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
/*
 * <% $module_c_filename %> - This file is in the public domain
 * Author: <% $author %>
 *
 * Generated on: <% $now %>
 * <% $module_name %> version: <% $module_version %>
 * Module::CAPIMaker version: <% $module_capimaker_version %>
 */

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

#ifdef __MINGW32__
#include <stdint.h>
#endif

#ifdef _MSC_VER
#include <stdlib.h>
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#endif

/* you may need to add a typemap for int64_t here if it is not defined
   by default in your C header files */

HV *<% $c_module_name %>_c_api_hash;
int <% $c_module_name %>_c_api_min_version;
int <% $c_module_name %>_c_api_max_version;

<%
    for my $n (sort keys %function) {
        my $f = $function{$n};
        $OUT .= "$f->{type} (*${c_module_name}_c_api_$n)($f->{args});\n";
    }
%>
int
perl_<% $c_module_name %>_load(int required_version) {
    dTHX;
    SV **svp;
    eval_pv("require <% $module_name %>", TRUE);
    if (SvTRUE(ERRSV)) return 0;

   <% $c_module_name %>_c_api_hash = get_hv("<% $module_name %>::C_API", 0);
    if (!<% $c_module_name %>_c_api_hash) {
        sv_setpv(ERRSV, "Unable to load <% $module_name %> C API");
        SvSETMAGIC(ERRSV);
        return 0;
    }

    svp = hv_fetch(<% $c_module_name %>_c_api_hash, "min_version", <% length "min_version" %>, 0);
    if (!svp) svp = hv_fetch(<% $c_module_name %>_c_api_hash, "version", <% length "version" %>, 1);
    if (!svp || !*svp) {
        sv_setpv(ERRSV, "Unable to retrieve C API version for <% $module_name %>");
        SvSETMAGIC(ERRSV);
        return 0;
    }
    <% $c_module_name %>_c_api_min_version = SvIV(*svp);

    svp = hv_fetch(<% $c_module_name %>_c_api_hash, "max_version", <% length "max_version" %>, 0);
    if (!svp) svp = hv_fetch(<% $c_module_name %>_c_api_hash, "version", <% length "version" %>, 1);
    if (!svp || !*svp) {
        sv_setpv(ERRSV, "Unable to retrieve C API version for <% $module_name %>");
        SvSETMAGIC(ERRSV);
        return 0;
    }
    <% $c_module_name %>_c_api_max_version = SvIV(*svp);

    if ((required_version < <% $c_module_name %>_c_api_min_version) ||
        (required_version > <% $c_module_name %>_c_api_max_version)) {
        sv_setpvf(ERRSV,
                  "<% $module_name %> C API version mismatch. "
                  "The installed module supports versions %d to %d but %d is required",
                  <% $c_module_name %>_c_api_min_version,
                  <% $c_module_name %>_c_api_max_version,
                  required_version);
        SvSETMAGIC(ERRSV);
        return 0;
    }

<%
    for my $n (sort keys %function) {
        my $len = length $n;
        $OUT .= <<EOC
    svp = hv_fetch(${c_module_name}_c_api_hash, "$n", $len, 0);
    if (!svp || !*svp) {
        sv_setpv(ERRSV, "Unable to fetch pointer '$n' C function from $module_name");
        SvSETMAGIC(ERRSV);
        return 0;
    }
    ${c_module_name}_c_api_$n = INT2PTR(void *, SvIV(*svp));
EOC
    }
%>
    return 1;
}