Skip to content

Instantly share code, notes, and snippets.

@liamzdenek
Last active December 24, 2015 02:49
Show Gist options
  • Save liamzdenek/6733424 to your computer and use it in GitHub Desktop.
Save liamzdenek/6733424 to your computer and use it in GitHub Desktop.
Attempt at using shared objects with Go
package main
import (
// this package reqiures libffi-dev (ubuntu)
"bitbucket.org/binet/go-ffi/pkg/ffi"
"fmt"
"unsafe"
)
import "C"
func main() {
// this would be an actual Test package if Cgo was supported in tests
lib, err := ffi.NewLibrary("./libshared.so")
if err != nil {
panic(err)
}
// first test, proof of concept
{
hello, err := lib.Fct("main.Test1", ffi.Pointer, []ffi.Type{})
if err != nil {
panic(err)
}
res := (uintptr)(hello().Uint())
str := C.GoString((*C.char)(unsafe.Pointer(res)))
if str != "hello dlopen()" {
fmt.Printf("First test failed, got back: %v = %v\n", string(str), []byte(str))
return
} else {
fmt.Printf("First test passed\n")
}
}
// second test, multiple returns
{
hello, err := lib.Fct("main.Test2", ffi.Pointer, []ffi.Type{ffi.Int, ffi.Int})
if err != nil {
panic(err)
}
res := hello(2, 1);
addr := unsafe.Pointer(uintptr(res.UnsafeAddr()));
int_size := C.int(unsafe.Sizeof(C.int(0)));
return_val_1 := C.GoBytes(addr, int_size);
return_val_2 := C.GoBytes(unsafe.Pointer(uintptr(addr)+uintptr(int_size)), int_size);
if return_val_1[0] != 3 || return_val_2[0] != 1 {
fmt.Printf("Second test failed, got values:\n");
fmt.Printf("\t1) %v\n\t2) %v\n", return_val_1, return_val_2);
return
} else {
fmt.Printf("Second test passed\n");
}
/*
addr2 := unsafe.Pointer(uintptr(addr) + unsafe.Sizeof(addr))
fmt.Printf("Addr2: %v\n", addr2);
str := C.GoBytes(addr, C.int(unsafe.Sizeof(C.int));
fmt.Printf("Str: %v\n", str);
str2 := C.GoBytes(), C.int(unsafe.Sizeof(C.int)));
fmt.Printf("Str2: %v\n", str2);
*/
/*
res := (uintptr)(hello(12, 13).Uint())
fmt.Printf("Res: %v\n", res);
str := C.GoBytes(unsafe.Pointer(res), C.int(8));
fmt.Printf("GoString: %v\n", str);
*/
}
// third test, one argument
// fourth test, multiple arguments
}
default:
gccgo -g -O0 -fPIC -shared shared.go -o libshared.so -lgcc
go build loader.go
package main
func main() {} // skeleton
func Test1() string {
return "hello dlopen()";
}
func Test2(i, j int) (int, int) {
return i+j, i-j
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment