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.
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.