stevieb has asked for the wisdom of the Perl Monks concerning the following question:

XS related question this time.

In an XS file, I'm wrapping several functions from a C library. However, one of the functions accepts an unsigned char data[8]. My distribution exports (@EXPORT_OK) both the C functions in their original naming convention (camelCase), and more Perlish versions (snake_case, where some provide extra functionality before calling the C version).

Now, this particular function, let's call it lcdCharDef(), I need to do some trickery around before allowing it to be available to end users.

Is there a way that I can do something like an "import as" for an XS function into the Perl module's code? Here's some mock/pseudo of what I'm wondering is possible:

sub lcdCharDef { ... return XS::lcdCharDef(...); }

Because the names clash, I can't call the C function within the same named Perl function, and I can't seem to figure out if there is a workaround for this, whether it be in the XS, or Perl.

Replies are listed 'Best First'.
Re: Accessing an XS function from a Perl function of the same name
by Anonymous Monk on Mar 04, 2017 at 00:16 UTC

      Thanks! I did some initial testing with this (which did work with some trickery upstream), but I believe what I'm going to do is remove all access to the C functions by their original names, and hide all of that so I don't have to do trickery or other things.

      If people want to use Perl, I'm thinking they are used to certain idioms, so perl style function calls are best. I don't remember why I offered the original C names anyway, probably because it was my first foray into wrapping C.

      I've learned a lot about wrapping libraries and some XS, and am burned by some initial decisions. Thankfully, most of the underlying core of my projects are not used directly, so I can muck with the API without much damage other than (hopefully) people I know are testing/working it.

        If you want to wrap a library function (let's call it 'foo') in an XS sub, and be able to call that XS sub from perl as 'foo', then you make use of the XS PREFIX option - which allows you to specify a prefix that will be automatically stripped from the XS sub when it is bound to perl.

        For example, specify PREFIX as 'wrap_this_', write the XS Sub as:
        int wrap_this_foo(int x) { return foo(x); }
        Then, when you call foo(16) in perl, wrap_this_foo(16) is executed.

        Here's an Inline::C demo that gets a perl function named 'foo' to execute a C function named 'foo', via an XS sub named 'wrap_this_foo' that wraps the C sub 'foo'.
        use strict; use warnings; use Inline C => Config => PREFIX => 'wrap_this_', BUILD_NOISY => 1, ; use Inline C => <<'END_C'; typedef int unbind; /* For this demo, we don't want foo * to bind to perl */ unbind foo(int x) { return x * 2; } int wrap_this_foo(int x){ return foo(x); } END_C print foo(16); # Outputs 32
        If you comment out the the wrap_this_foo XS sub and re-run the script then you get:
        Undefined subroutine &main::foo called at try.pl line 25.
        I hope that proves that the original run was, in fact, calling wrap_this_foo and not directly calling the C function foo (which is invisible to perl).
        Update: It's invisible to perl because perl's typemap doesn't explain how to deal with the type 'unbind'.

        Cheers,
        Rob