|
||
---|---|---|
.. | ||
internal | ||
objc | ||
.gitignore | ||
abi_amd64.h | ||
abi_arm64.h | ||
cgo.go | ||
dlerror.go | ||
dlfcn.go | ||
dlfcn_darwin.go | ||
dlfcn_freebsd.go | ||
dlfcn_linux.go | ||
dlfcn_nocgo_linux.go | ||
dlfcn_stubs.s | ||
func.go | ||
go_runtime.go | ||
is_ios.go | ||
LICENSE | ||
nocgo.go | ||
README.md | ||
sys_amd64.s | ||
sys_arm64.s | ||
sys_unix_arm64.s | ||
syscall.go | ||
syscall_cgo_linux.go | ||
syscall_sysv.go | ||
syscall_windows.go | ||
zcallback_amd64.s | ||
zcallback_arm64.s |
purego
A library for calling C functions from Go without Cgo.
Motivation
The Ebitengine game engine was ported to use only Go on Windows. This enabled
cross-compiling to Windows from any other operating system simply by setting GOOS=windows
. The purego project was
born to bring that same vision to the other platforms supported by Ebitengine.
Benefits
- Simple Cross-Compilation: No C means you can build for other platforms easily without a C compiler.
- Faster Compilation: Efficiently cache your entirely Go builds.
- Smaller Binaries: Using Cgo generates a C wrapper function for each C function called. Purego doesn't!
- Dynamic Linking: Load symbols at runtime and use it as a plugin system.
- Foreign Function Interface: Call into other languages that are compiled into shared objects.
Example
This example only works on macOS and Linux. For a complete example look at libc which supports Windows and FreeBSD.
package main
import (
"fmt"
"runtime"
"github.com/ebitengine/purego"
)
func getSystemLibrary() string {
switch runtime.GOOS {
case "darwin":
return "/usr/lib/libSystem.B.dylib"
case "linux":
return "libc.so.6"
default:
panic(fmt.Errorf("GOOS=%s is not supported", runtime.GOOS))
}
}
func main() {
libc, err := purego.Dlopen(getSystemLibrary(), purego.RTLD_NOW|purego.RTLD_GLOBAL)
if err != nil {
panic(err)
}
var puts func(string)
purego.RegisterLibFunc(&puts, libc, "puts")
puts("Calling C from Go without Cgo!")
}
Then to run: CGO_ENABLED=0 go run main.go
External Code
Purego uses code that originates from the Go runtime. These files are under the BSD-3 License that can be found in the Go Source. This is a list of the copied files:
abi_*.h
from packageruntime/cgo
zcallback_darwin_*.s
from packageruntime
internal/fakecgo/abi_*.h
from packageruntime/cgo
internal/fakecgo/asm_GOARCH.s
from packageruntime/cgo
internal/fakecgo/callbacks.go
from packageruntime/cgo
internal/fakecgo/go_GOOS_GOARCH.go
from packageruntime/cgo
internal/fakecgo/iscgo.go
from packageruntime/cgo
internal/fakecgo/setenv.go
from packageruntime/cgo
internal/fakecgo/freebsd.go
from packageruntime/cgo
The files abi_*.h
and internal/fakecgo/abi_*.h
are the same because Bazel does not support cross-package use of #include
so we need each one once per package. (cf. issue)