NAME

FFI::Platypus::Lang::Go - Documentation and tools for using Platypus with Go

VERSION

version 0.03

SYNOPSIS

Go code:

package main

import "C"

//export add
func add(x, y int) int {
    return x + y
}

func main() {}

Perl code:

use FFI::Platypus 2.00;
use FFI::CheckLib qw( find_lib_or_die );
use File::Basename qw( dirname );

my $ffi = FFI::Platypus->new(
  api  => 2,
  lib  => './add.so',
  lang => 'Go',
);
$ffi->attach( add => ['goint', 'goint'] => 'goint' );

print add(1,2), "\n";  # prints 3

DESCRIPTION

This distribution is the Go language plugin for Platypus. It provides the definition for native Go types, like goint and gostring. It also provides a FFI::Build interface for building Perl extensions written in Go (see FFI::Build::File::GoMod for details).

EXAMPLES

The examples in this discussion are bundled with this distribution and can be found in the examples directory.

Passing and Returning Integers

Go

package main

import "C"

//export add
func add(x, y int) int {
    return x + y
}

func main() {}

Perl

use FFI::Platypus 2.00;
use FFI::CheckLib qw( find_lib_or_die );
use File::Basename qw( dirname );

my $ffi = FFI::Platypus->new(
  api  => 2,
  lib  => './add.so',
  lang => 'Go',
);
$ffi->attach( add => ['goint', 'goint'] => 'goint' );

print add(1,2), "\n";  # prints 3

Execute

$ go build -o add.so -buildmode=c-shared add.go
$ perl add.pl
3

Discussion

The Go code has to:

1 Import the pseudo package "C"
2 Mark any exported function with the command //export
3 Include a main function, even if you do not use it.

From the Perl side, the Go types have a go prefix, so int in Go is goint in Perl.

Aside from that passing basic types like integers and floats is trivial with FFI.

Module

Go

/*
 * borrowed from
 * https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf
 */

package main

import "C"

import (
	"fmt"
	"math"
	"sort"
	"sync"
)

var count int
var mtx sync.Mutex

//export Add
func Add(a, b int) int { return a + b }

//export Cosine
func Cosine(x float64) float64 { return math.Cos(x) }

//export Sort
func Sort(vals []int) { sort.Ints(vals) }

//export Log
func Log(msg string) int {
	mtx.Lock()
	defer mtx.Unlock()
	fmt.Println(msg)
	count++
	return count
}

func main() {}

Perl

Module:

package Awesome::FFI;

use strict;
use warnings;
use FFI::Platypus;
use FFI::Go::String;
use base qw( Exporter );

our @EXPORT_OK = qw( Add Cosine Log );

my $ffi = FFI::Platypus->new( api => 1, lang => 'Go' );
# See FFI::Platypus::Bundle for the how and why
# bundle works.
$ffi->bundle;

$ffi->attach( Add    => ['goint','goint'] => 'goint'     );
$ffi->attach( Cosine => ['gofloat64'    ] => 'gofloat64' );
$ffi->attach( Log    => ['gostring'     ] => 'goint'     );

1;

Test:

use Test2::V0 -no_srand => 1;
use Awesome::FFI qw( Add Cosine Log );
use Capture::Tiny qw( capture );
use FFI::Go::String;

is( Add(1,2), 3 );
is( Cosine(0), 1.0 );

is(
  [capture { Log("Hello Perl!") }],
  ["Hello Perl!\n", '', 1]
);

done_testing;

Execute

$ prove -lvm t/awesome_ffi.t
t/awesome_ffi.t ..
ok 1
ok 2
ok 3
1..3
ok
All tests successful.
Files=1, Tests=3,  1 wallclock secs ( 0.01 usr  0.00 sys +  1.28 cusr  0.48 csys =  1.77 CPU)
Result: PASS

Discussion

This is a full working example of a Perl distribution / module included in the examples/Awesome-FFI directory.

SEE ALSO

FFI::Platypus

More about FFI and Platypus itself.

FFI::Platypus::Type::GoString

Type plugin for the go string type.

FFI::Go::String

Low level interface to the go string type.

FFI::Build::File::GoMod

FFI::Build class for handling Go modules.

Calling Go Functions from Other Languages using C Shared Libraries

AUTHOR

Author: Graham Ollis <plicease@cpan.org>

Contributors:

Graham TerMarsch (GTERMARS)

COPYRIGHT AND LICENSE

This software is copyright (c) 2018-2022 by Graham Ollis.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.