Perl Integration

Bidirectional integration between Strada and Perl 5.

Strada provides two-way integration with Perl:

Strada Calling Perl

The perl5 module allows Strada programs to embed and interact with a Perl 5 interpreter. This gives you access to the entire CPAN ecosystem from Strada.

Basic Usage

use lib "lib";
use perl5;

func main() int {
    # Initialize Perl (required first)
    perl5::init();

    # Evaluate expressions
    my str $result = perl5::eval("2 ** 10");
    say("2^10 = " . $result);  # 1024

    # Define and call subroutines
    perl5::run("sub double { return $_[0] * 2; }");
    my str $doubled = perl5::call("double", "21");
    say("21 doubled = " . $doubled);  # 42

    # Use CPAN modules
    if (perl5::use_module("List::Util") == 1) {
        perl5::run("@nums = (1, 5, 3, 9, 2);");
        my str $max = perl5::eval("List::Util::max(@nums)");
        say("Max: " . $max);  # 9
    }

    # Cleanup
    perl5::shutdown();
    return 0;
}

Compilation

You need to link against libperl when compiling:

# Compile with Perl embedding flags
./strada myapp.strada $(perl -MExtUtils::Embed -e ccopts -e ldopts)

API Reference

Function Description
perl5::init() Initialize Perl interpreter. Returns 1 on success, 0 on failure.
perl5::shutdown() Shutdown the Perl interpreter and free resources.
perl5::is_init() Check if Perl is initialized. Returns 1 if yes, 0 if no.
perl5::eval($code) Evaluate Perl code and return the result as a string.
perl5::run($code) Execute Perl code without returning a value.
perl5::call($sub, $arg) Call a Perl subroutine with a single string argument.
perl5::call_noargs($sub) Call a Perl subroutine with no arguments.
perl5::call_list($sub, $sep) Call a sub that returns a list, join with separator.
perl5::use_module($mod) Load a Perl module (like use Module;). Returns 1 on success.
perl5::require_module($mod) Require a Perl module. Returns 1 on success.
perl5::set_var($name, $val) Set a Perl scalar variable.
perl5::get_var($name) Get the value of a Perl scalar variable.
perl5::add_inc($path) Add a path to Perl's @INC.
perl5::get_error() Get the last Perl error ($@).

Working with Variables

# Set and get Perl variables
perl5::set_var("$name", "Alice");
perl5::set_var("$age", "30");

my str $name = perl5::get_var("$name");
say("Name: " . $name);  # Alice

# Work with arrays and hashes in Perl
perl5::run("@colors = qw(red green blue);");
perl5::run("%person = (name => 'Bob', age => 25);");

my str $count = perl5::eval("scalar(@colors)");
my str $person_name = perl5::eval("$person{name}");

Using CPAN Modules

# HTTP requests with LWP
if (perl5::use_module("LWP::Simple") == 1) {
    my str $html = perl5::eval("get('http://example.com')");
    say("Got " . length($html) . " bytes");
}

# JSON parsing
if (perl5::use_module("JSON") == 1) {
    perl5::set_var("$json_str", "{\"name\":\"test\"}");
    perl5::run("$data = decode_json($json_str);");
    my str $name = perl5::eval("$data->{name}");
}

# Database access with DBI
if (perl5::use_module("DBI") == 1) {
    perl5::run("$dbh = DBI->connect('dbi:SQLite:test.db');");
    perl5::run("$sth = $dbh->prepare('SELECT * FROM users');");
    perl5::run("$sth->execute();");
    # ... process results
}

XS Module Support

XS-based Perl modules (compiled modules like POSIX, JSON::XS, DBI) require the Perl library to be preloaded:

# Find your libperl path
perl -MConfig -e 'print $Config{archlib}'

# Run with LD_PRELOAD
LD_PRELOAD=/lib/x86_64-linux-gnu/libperl.so.5.38 ./myapp

Pure Perl modules work without this workaround.

Error Handling

# Check for errors after eval
my str $result = perl5::eval("some_code()");
my str $error = perl5::get_error();

if (length($error) > 0) {
    say("Perl error: " . $error);
} else {
    say("Result: " . $result);
}

Perl Calling Strada

The Strada Perl module allows Perl programs to load and call functions from compiled Strada shared libraries. This lets you write performance-critical code in Strada and use it from Perl.

Setup

# Build the Perl XS module
cd perl/Strada
perl Makefile.PL
make
make test
make install  # optional

Creating a Strada Library

First, write your Strada code as a library:

# mylib.strada
package mylib;

func add(int $a, int $b) int {
    return $a + $b;
}

func greet(str $name) str {
    return "Hello, " . $name . "!";
}

func sum_list(scalar $items) int {
    my int $sum = 0;
    foreach my int $x ($items) {
        $sum = $sum + $x;
    }
    return $sum;
}

Compile it as a shared library:

./strada --shared mylib.strada
# Creates mylib.so

Using from Perl

#!/usr/bin/perl
use Strada;

# Load the library
my $lib = Strada::Library->new('./mylib.so');

# Call functions using namespace syntax
my $sum = $lib->call('mylib::add', 10, 20);
print "10 + 20 = $sum\n";  # 30

my $greeting = $lib->call('mylib::greet', 'Perl');
print "$greeting\n";  # Hello, Perl!

# Pass arrays
my $total = $lib->call('mylib::sum_list', [1, 2, 3, 4, 5]);
print "Sum: $total\n";  # 15

# Unload when done
$lib->unload();

Function Naming Convention

Strada functions are exported as package_function (underscore-separated). The Perl module accepts both styles:

Strada Declaration C Name Perl Call (both work)
package foo; func bar() foo_bar 'foo_bar' or 'foo::bar'
package utils; func format() utils_format 'utils_format' or 'utils::format'
package MyLib; func process() MyLib_process 'MyLib_process' or 'MyLib::process'
Namespace syntax supported: The Perl module automatically converts :: to _, so you can use familiar Strada/Perl syntax like $lib->call('mylib::add', 1, 2).

Type Conversion

Types are automatically converted between Strada and Perl:

Strada Type Perl Type
int Integer (IV)
num Float (NV)
str String (PV)
array Array reference
hash Hash reference
undef undef

Use Cases

Access CPAN from Strada

Use any of the thousands of CPAN modules from your Strada programs:

perl5::init();

# Parse YAML
perl5::use_module("YAML");
my str $yaml = perl5::eval("YAML::Dump({name => 'test'})");

# Send email
perl5::use_module("Email::Simple");
perl5::use_module("Email::Sender::Simple");

# Date handling
perl5::use_module("DateTime");
my str $now = perl5::eval("DateTime->now->iso8601");

perl5::shutdown();

High-Performance Code from Perl

Write performance-critical code in compiled Strada, call from Perl:

#!/usr/bin/perl
use Strada;

my $lib = Strada::Library->new('./libcompute.so');

# Strada handles the heavy lifting
for my $data (@large_dataset) {
    my $result = $lib->call('compute::process', $data);
    push @results, $result;
}

$lib->unload();

Mixed Language Projects

Combine the strengths of both languages:

Directory Structure

lib/
  perl5.strada           # Strada module for calling Perl

perl/
  Strada/
    Strada.xs            # XS implementation
    Strada.pm            # Perl module
    Makefile.PL          # Build configuration
    t/
      01_basic.t         # Test suite

See Also