Invoke Go functions from Php.
Note
You will need Go installed on your machine.
Write your Go program, for example in a goffi.go
file.
// ./goffi.go
package main
import "C"
func main() {}
//export DoubleIt
func DoubleIt(x int) int {
return x * 2
}
The //export DoubleIt
annotation will make it so that the function DoubleIt()
will be exposed.
Compile your program to a shared object
go build -o libgoffi.so -buildmode=c-shared goffi.go
This will create 2 files, your shared object libgoffi.so
and its C header file libgoffi.h
.
Resolve the C header file's preprocessor directives.
cpp -P ./libgoffi.h ./libgoffi.static.h
This will create a libgoffi.static.h
file, this file must be located in the same directory as the libgoffi.so
file.
Now use goffi()
to interop with your Go program from Php.
<?php
// src/main.php
use CatPaw\Core\Unsafe;
use function CatPaw\Core\goffi;
use function CatPaw\Core\anyError;
interface Contract {
/**
* Double a value.
*/
function DoubleIt(int $value):int;
}
function main():Unsafe{
return anyError(function(){
$lib = goffi(Contract::class, './libgoffi.so')->try();
$doubled = $lib->DoubleIt(3);
echo "doubled: $doubled\n";
});
}
Note
If any of your interface methods doesn't specify a return type, the goffi()
call will fail.
Run the program.
composer prod:start
It should print
doubled: 6
Given the following Go program
package main
import "C"
func main() {}
//export Greeting
func Greeting(name *C.char) *C.char {
return C.CString("hello " + C.GoString(name))
}
Call Greeting from php like so
<?php
use CatPaw\Core\Unsafe;
use function CatPaw\Core\anyError;
use function CatPaw\Core\goffi;
interface Contract {
function Greeting(string $name):string;
}
function main():Unsafe {
return anyError(function() {
$goffi = goffi(Contract::class, './libgoffi.so')->try();
echo $goffi->Greeting('world').PHP_EOL;
});
}
Run it with
composer prod:start
it should print hello world
to the terminal.
More quality of life improvements will come in the future.
Discussion available here.
Standalone example available here.