Extism

 view release on metacpan or  search on metacpan

lib/Extism.pm  view on Meta::CPAN


Extism L<https://extism.org/> is a cross-language framework for building
with WebAssembly. This distribution integrates Extism into Perl so Perl
programmers can easily use WebAssembly. Possibily to add a Plugin system
into their application or to integrate native deps without the headache
of native builds.

=head1 SYNOPSIS

    use Extism ':all';
    my $wasm = do { local(@ARGV, $/) = 'count_vowels.wasm'; <> };
    my $plugin = Extism::Plugin->new($wasm, {wasi => 1});
    my $output = $plugin->call('count_vowels', "this is a test");

=head1 EXAMPLES

See script/demo-perl-extism and t/02-extism.t

=head1 SUPPORT AND DOCUMENTATION

You can find documentation for this module with the perldoc command.

lib/Extism/ppport.h  view on Meta::CPAN

  if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) {
    my $hint = $hints{$func};
    $hint =~ s/^/   /mg;
    print "   --- hint for $func ---\n", $hint;
  }
  $rv || 0;
}

sub usage
{
  my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms;
  my %M = ( 'I' => '*' );
  $usage =~ s/^\s*perl\s+\S+/$^X $0/;
  $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g;

  print <<ENDUSAGE;

Usage: $usage

See perldoc $0 for details.

ENDUSAGE

  exit 2;
}

sub strip
{
  my $self = do { local(@ARGV,$/)=($0); <> };
  my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms;
  $copy =~ s/^(?=\S+)/    /gms;
  $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms;
  $self =~ s/^SKIP.*(?=^__DATA__)/SKIP
if (\@ARGV && \$ARGV[0] eq '--unstrip') {
  eval { require Devel::PPPort };
  \$@ and die "Cannot require Devel::PPPort, please install.\\n";
  if (eval \$Devel::PPPort::VERSION < $VERSION) {
    die "$0 was originally generated with Devel::PPPort $VERSION.\\n"
      . "Your Devel::PPPort is only version \$Devel::PPPort::VERSION.\\n"

script/demo-perl-extism  view on Meta::CPAN

use Extism;

# print Extism Version
say "Extism version: " . Extism::version() . "\n";

# Should fail with an error message, invalid manifest
my $notplugin = Extism::Plugin->new('', {wasi => 1}) // "did not load as expected";
say "notplugin: $notplugin\n";

# load count vowels and test
my $wasm = do { local(@ARGV, $/) = 'count_vowels.wasm'; <> };
my $plugin = Extism::Plugin->new($wasm, {wasi => 1});
my $input = "this is a test";
say "count_vowels - input: $input";
my $output = $plugin->call('count_vowels', $input);
say "count_vowels - output: $output\n";

say "plugin->reset: ". $plugin->reset() . "\n";

# load fail and call run_test, it should fail
my $failwasm = do { local(@ARGV, $/) = 'fail.wasm'; <> };
my $failplugin = Extism::Plugin->new($failwasm, {wasi => 1});
my $failed = $failplugin->call('run_test', "") // "call failed as expected";
say "failplugin: $failed\n";

t/02-extism.t  view on Meta::CPAN


# test failing plugin throws an exception
eval {
    my $notplugin = Extism::Plugin->new('');
    fail('Extism::Plugin->new("") should throw an exception');
};
ok($@);

# test succeeding plugin new in scalar and list context
# also text various Plugin:: functions
my $wasm = do { local(@ARGV, $/) = 'count_vowels.wasm'; <> };
{
    my $plugin = Extism::Plugin->new($wasm, {wasi => 1});
    ok($plugin);
    my $output = $plugin->call('count_vowels', "this is a test");
    ok($output);
    my $outputhash = decode_json($output);
    ok($outputhash->{count} == 4);
    ok(length($plugin->id) == 16);
    ok($plugin->function_exists('count_vowels'));
    ok(!$plugin->function_exists('does_not_exist'));

t/02-extism.t  view on Meta::CPAN

    my ($output) = $plugin->call('count_vowels', "this is a test");
    ok($output);
    my $outputhash = decode_json($output);
    ok($outputhash->{count} == 4);
}

# test log_file and call on failing plugin
{
    my ($error_fh, $filename) = tempfile();
    Extism::log_file($filename, "error");
    my $failwasm = do { local(@ARGV, $/) = 'fail.wasm'; <> };
    my $failplugin = Extism::Plugin->new($failwasm, {wasi => 1});
    eval {
        my $failed = $failplugin->call('run_test', "");
        fail('calling run_test in failplugin should throw an exception');
    };
    ok($@);
    my $rc = read($error_fh, my $filler, 1);
    ok($rc == 1);
    unlink($filename);
    Extism::log_file("/dev/stdout", "error");

t/02-extism.t  view on Meta::CPAN

});
ok($voidfunction);
my $paramsfunction = Extism::Function->new("hello_params", [Extism_F64, Extism_I32, Extism_F32, Extism_I64], [Extism_I64], sub {
    print "hello_params: ".join(' ', @_) . "\n";
    return 18446744073709551615;
});
ok($paramsfunction);
my $withnamespace = Extism::Function->new("with_namespace", [], [], sub {
}, 'namespace');
ok($withnamespace);
my $hostwasm = do { local(@ARGV, $/) = 'host.wasm'; <> };
my $fplugin = Extism::Plugin->new($hostwasm, {functions => [$voidfunction, $paramsfunction], wasi => 1});
ok($fplugin);
ok(defined $fplugin->call('call_hello_void'));
ok(defined $fplugin->call('call_hello_params'));

# test more advanced host functions
my $count_vowels_kv = encode_json({
    wasm => [
        {
            #url => "https://github.com/extism/plugins/releases/latest/download/count_vowels_kvstore.wasm"



( run in 1.368 second using v1.01-cache-2.11-cpan-49f99fa48dc )