fee71e7740
Feature/postprocessing * tests * passtest * fixshorttests * mosttests * improvingbasedockerfile * testspeeds * testing * host * canparallel * clean * passfullsuite * singlepagemax * test * findfeatures * findstables * tbls * tablestoo * tablestoo * lateraltests * tableloc * cleanup * inlinetable * childids * cleanup * tests
104 lines
2.6 KiB
Markdown
104 lines
2.6 KiB
Markdown
# ffi
|
|
[](https://pkg.go.dev/github.com/jupiterrider/ffi)
|
|
|
|
A purego binding for libffi.
|
|
|
|
## Purpose
|
|
You can use [purego](https://github.com/ebitengine/purego) to call C code without cgo. ffi provides extra functionality (e.g. passing and returning structs by value).
|
|
|
|
## Requirements
|
|
### OS/Architecture
|
|
- darwin/amd64
|
|
- darwin/arm64
|
|
- freebsd/amd64
|
|
- freebsd/arm64
|
|
- linux/amd64
|
|
- linux/arm64
|
|
- windows/amd64
|
|
- windows/arm64
|
|
|
|
### Software
|
|
[libffi](https://github.com/libffi/libffi) is preinstalled on most distributions, because it also is a dependency of Python and Ruby. If not, you can install it explicitly:
|
|
|
|
#### Arch Linux
|
|
```sh
|
|
sudo pacman -S libffi
|
|
```
|
|
|
|
#### Debian 12, Ubuntu 22.04, Ubuntu 24.04
|
|
```sh
|
|
sudo apt install libffi8
|
|
```
|
|
|
|
#### Debian 11, Ubuntu 20.04
|
|
```sh
|
|
sudo apt install libffi7
|
|
```
|
|
|
|
#### FreeBSD
|
|
```sh
|
|
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).
|
|
|
|
#### Windows
|
|
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](https://www.python.org/downloads/windows/) of Python.
|
|
|
|
#### macOS
|
|
You can use [Homebrew](https://brew.sh/) to install libffi:
|
|
```sh
|
|
brew install libffi
|
|
```
|
|
Note: If dlopen can't find the libffi.8.dylib file, you can try setting this environment variable:
|
|
```sh
|
|
export DYLD_FALLBACK_LIBRARY_PATH=$DYLD_FALLBACK_LIBRARY_PATH:/opt/homebrew/opt/libffi/lib
|
|
```
|
|
|
|
## Examples
|
|
In this example we use the puts function inside the standard C library to print "Hello World!" to the console:
|
|
|
|
```c
|
|
int puts(const char *s);
|
|
```
|
|
|
|
```golang
|
|
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](examples) folder of this repository.
|