github.com/jwijenbergh/purego@v0.0.0-20240126093400-70ff3a61df13/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.com/channels/842049801528016967/1123106378731487345)!
    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))