A purego binding for libffi.
You can use purego to call C code without cgo. ffi provides extra functionality (e.g. passing and returning structs by value).
- freebsd/amd64
- freebsd/arm64
- linux/amd64
- linux/arm64
- windows/amd64
- windows/arm64
libffi is preinstalled on most distributions, because it also is a dependency of Python and Ruby. If not, you can install it explicitly:
sudo pacman -S libffi
sudo apt install libffi8
sudo apt install libffi7
pkg install libffi
Note: Use this -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std"
build flag when cross compiling or having CGO_ENABLED set to 0 (FreeBSD only).
You need a libffi-8.dll
next to the executable/root folder of your project or inside C:\Windows\System32. If you don't want to build libffi from source, you can find this dll for example inside the Windows embeddable package of Python.
In this example we use the puts function inside the standard C library to print "Hello World!" to the console:
int puts(const char *s);
package main
import (
"unsafe"
"github.com/ebitengine/purego"
"github.com/jupiterrider/ffi"
"golang.org/x/sys/unix"
)
func main() {
// open the C library
libm, err := purego.Dlopen("libc.so.6", purego.RTLD_LAZY)
if err != nil {
panic(err)
}
// get the address of puts
puts, err := purego.Dlsym(libm, "puts")
if err != nil {
panic(err)
}
// describe the function's signature
var cif ffi.Cif
if status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, &ffi.TypeSint32, &ffi.TypePointer); status != ffi.OK {
panic(status)
}
// convert the go string into a pointer
text, _ := unix.BytePtrFromString("Hello World!")
// call the puts function
var result ffi.Arg
ffi.Call(&cif, puts, unsafe.Pointer(&result), unsafe.Pointer(&text))
}
You can find more examples inside the examples folder of this repository.