Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to write a C function and be able to call it from perl

Tags:

perl

I have been programming C for a while. Now I need to write a C program that perl can call. It should have the same syntax as the following dummy perl function: Take two inputs, both are strings (may contain binary characters, even "\x00"), output a new string.

Of course, algorithm of the function will be more complex, that's why I need to do it in C.

sub dummy {
    my ($a, $b) = @_;
    return $a . $b;
}

I have briefly looked at SWIG for the implementation, but taking input/ouput other than an integer is not easy, hope someone can give a concrete example.

Thanks in advance.

UPDATE: Got a great example from Rob (author of the Inline::C module in cpan), thanks!

##############################
use warnings;
use strict;
use Devel::Peek;

use Inline C => Config =>
BUILD_NOISY => 1,
;

use Inline C => <<'EOC';

SV * foo(SV * in) {
 SV * ret;

 STRLEN len;
 char *tmp = SvPV(in, len);
 ret = newSVpv(tmp, len);
 sv_catpvn(ret, tmp, len);
 return ret;

}

EOC

my $in = 'hello' . "\x00" . 'world';
my $ret = foo($in);


Dump($in);
print "\n";
Dump ($ret);

##############################
like image 684
packetie Avatar asked Apr 06 '14 13:04

packetie


1 Answers

Perl has a glue language called XS for this kind of thing. It knows about mappings between Perl data types and C types. For example, a C function

char *dummy(char *a, int len_a, char *b, int len_b);

could be wrapped by the XS code

MODULE = Foo    PACKAGE = Foo

char *
dummy(char *a, int length(a), char *b, int length(b));

The Foo.xs file will be compiled when the module is installed, all relevant build tool chains have support for XS.

Argument conversion code will be generated automatically, so that the function can be called in Perl as Foo::dummy("foo", "bar"), once the XS code has been loaded from Perl:

package Foo;
use parent 'DynaLoader';
Foo->bootstrap;

There is an XS tutorial in the perl documentation, and reference documentation in perlxs.

XS is a good choice for modules, but is awkward for one-off scripts. The Inline::C module allows you to embed the glue C code directly into your Perl script and will take care of automatic compilation whenever the C code changes. However, less code can be generated automatically with this approach.

like image 174
amon Avatar answered Nov 09 '22 19:11

amon