github.com/ebitengine/purego@v0.8.0-alpha.2.0.20240512170805-6cd12240d332/README.md (about) 1 # purego 2 [![Go Reference](https://pkg.go.dev/badge/github.com/ebitengine/purego?GOOS=darwin.svg)](https://pkg.go.dev/github.com/ebitengine/purego?GOOS=darwin) 3 4 A library for calling C functions from Go without Cgo. 5 6 > This is beta software so expect bugs and potentially API breaking changes 7 > but each release will be tagged to avoid breaking people's code. 8 > Bug reports are encouraged. 9 10 ## Motivation 11 12 The [Ebitengine](https://github.com/hajimehoshi/ebiten) game engine was ported to use only Go on Windows. This enabled 13 cross-compiling to Windows from any other operating system simply by setting `GOOS=windows`. The purego project was 14 born to bring that same vision to the other platforms supported by Ebitengine. 15 16 ## Benefits 17 18 - **Simple Cross-Compilation**: No C means you can build for other platforms easily without a C compiler. 19 - **Faster Compilation**: Efficiently cache your entirely Go builds. 20 - **Smaller Binaries**: Using Cgo generates a C wrapper function for each C function called. Purego doesn't! 21 - **Dynamic Linking**: Load symbols at runtime and use it as a plugin system. 22 - **Foreign Function Interface**: Call into other languages that are compiled into shared objects. 23 - **Cgo Fallback**: Works even with CGO_ENABLED=1 so incremental porting is possible. 24 This also means unsupported GOARCHs (freebsd/riscv64, linux/mips, etc.) will still work 25 except for float arguments and return values. 26 27 ## Supported Platforms 28 29 - **FreeBSD**: amd64, arm64 30 - **Linux**: amd64, arm64 31 - **macOS / iOS**: amd64, arm64 32 - **Windows**: 386*, amd64, arm*, arm64 33 34 `*` These architectures only support SyscallN and NewCallback 35 36 ## Example 37 38 This example only works on macOS and Linux. For a complete example look at [libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows and FreeBSD. 39 40 ```go 41 package main 42 43 import ( 44 "fmt" 45 "runtime" 46 47 "github.com/ebitengine/purego" 48 ) 49 50 func getSystemLibrary() string { 51 switch runtime.GOOS { 52 case "darwin": 53 return "/usr/lib/libSystem.B.dylib" 54 case "linux": 55 return "libc.so.6" 56 default: 57 panic(fmt.Errorf("GOOS=%s is not supported", runtime.GOOS)) 58 } 59 } 60 61 func main() { 62 libc, err := purego.Dlopen(getSystemLibrary(), purego.RTLD_NOW|purego.RTLD_GLOBAL) 63 if err != nil { 64 panic(err) 65 } 66 var puts func(string) 67 purego.RegisterLibFunc(&puts, libc, "puts") 68 puts("Calling C from Go without Cgo!") 69 } 70 ``` 71 72 Then to run: `CGO_ENABLED=0 go run main.go` 73 74 ## Questions 75 76 If you have questions about how to incorporate purego in your project or want to discuss 77 how it works join the [Discord](https://discord.gg/HzGZVD6BkY)! 78 79 ### External Code 80 81 Purego uses code that originates from the Go runtime. These files are under the BSD-3 82 License that can be found [in the Go Source](https://github.com/golang/go/blob/master/LICENSE). 83 This is a list of the copied files: 84 85 * `abi_*.h` from package `runtime/cgo` 86 * `zcallback_darwin_*.s` from package `runtime` 87 * `internal/fakecgo/abi_*.h` from package `runtime/cgo` 88 * `internal/fakecgo/asm_GOARCH.s` from package `runtime/cgo` 89 * `internal/fakecgo/callbacks.go` from package `runtime/cgo` 90 * `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo` 91 * `internal/fakecgo/iscgo.go` from package `runtime/cgo` 92 * `internal/fakecgo/setenv.go` from package `runtime/cgo` 93 * `internal/fakecgo/freebsd.go` from package `runtime/cgo` 94 95 The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of 96 `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))