Skip to content

Latest commit

 

History

History
127 lines (94 loc) · 2.42 KB

28.goffi.md

File metadata and controls

127 lines (94 loc) · 2.42 KB

Goffi

Invoke Go functions from Php.

Usage

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

Usage with strings

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.

Other notes

More quality of life improvements will come in the future.

Discussion available here.

Standalone example available here.