Documentation
¶
Index ¶
Examples ¶
Constants ¶
const ( Void = iota Int Float Double Longdouble Uint8 Sint8 Uint16 Sint16 Uint32 Sint32 Uint64 Sint64 Struct Pointer Complex )
These constants are used for the Type field of Type.
const TrampolineSize = 32
Variables ¶
var ( TypeVoid = Type{1, 1, Void, nil} TypeUint8 = Type{1, 1, Uint8, nil} TypeSint8 = Type{1, 1, Sint8, nil} TypeUint16 = Type{2, 2, Uint16, nil} TypeSint16 = Type{2, 2, Sint16, nil} TypeUint32 = Type{4, 4, Uint32, nil} TypeSint32 = Type{4, 4, Sint32, nil} TypeUint64 = Type{8, 8, Uint64, nil} TypeSint64 = Type{8, 8, Sint64, nil} TypeFloat = Type{4, 4, Float, nil} TypeDouble = Type{8, 8, Double, nil} TypePointer = Type{8, 8, Pointer, nil} TypeLongdouble = Type{16, 16, Longdouble, nil} TypeComplexFloat = Type{8, 4, Complex, &[]*Type{&TypeFloat, nil}[0]} TypeComplexDouble = Type{16, 8, Complex, &[]*Type{&TypeDouble, nil}[0]} TypeComplexLongdouble = Type{32, 16, Complex, &[]*Type{&TypeLongdouble, nil}[0]} )
Predefined variables for primitive data types.
For bool you can use TypeUint8 and check its value:
byte(returnValue) != 0
A string is just an array of characters in C (often seen as char * or const char *). Use TypePointer for that.
To convert strings between C and Go take a look at golang.org/x/sys/unix.BytePtrFromString and golang.org/x/sys/unix.BytePtrToString. The Windows counterparts are golang.org/x/sys/windows.BytePtrFromString and golang.org/x/sys/windows.BytePtrToString.
Slices are treated as pointers as well. You can use unsafe.Slice to convert a pointer into a slice.
Functions ¶
func Call ¶
Call calls the function fn according to the description given in cif. cif must have already been prepared using PrepCif.
- fn is the address of the desired function. Use purego.Dlsym to get one.
- rValue is a pointer to a variable that will hold the result of the function call. Provide nil if the function has no return value. You cannot use integer types smaller than 8 bytes here (float32 and structs are not affected). Use Arg instead and typecast afterwards.
- aValues are pointers to the argument values. Leave empty or provide nil if the function takes none.
Example:
// C function: // int ilogb(double x); var result ffi.Arg x := 1.0 ffi.Call(&cif, ilogb, unsafe.Pointer(&result), unsafe.Pointer(&x)) fmt.Printf("%d\n", int32(result))
func ClosureFree ¶ added in v0.3.0
func ClosureFree(writable *Closure)
ClosureFree is used to free memory allocated by ClosureAlloc.
func NewCallback ¶ added in v0.3.0
NewCallback converts the Go function fn into a C function pointer. The returned value can be used as parameter in PrepClosureLoc.
Types ¶
type Arg ¶
type Arg uint64
Arg can be used as a return value for functions, which return integers smaller than 8 bytes.
See Call.
type Callback ¶ added in v0.3.0
type Callback func(cif *Cif, ret unsafe.Pointer, args *unsafe.Pointer, userData unsafe.Pointer) uintptr
Callback has the following parameters:
- cif is the same object that was passed to PrepClosureLoc.
- ret is a pointer to the memory used for the function's return value. If the function is declared as returning void, then this value is garbage and should not be used.
- args is a C array of pointers to the arguments. You can use unsafe.Slice to convert it.
- userData is the same data that was passed to PrepClosureLoc.
The returned uintptr can be ignored. It's just there for compatibility reasons.
Example:
// We assume that the closure has the following signature: // int64_t Add(int64_t a, int64_t b); cb := ffi.NewCallback(func(cif *ffi.Cif, ret unsafe.Pointer, args *unsafe.Pointer, userData unsafe.Pointer) uintptr { arguments := unsafe.Slice(args, cif.NArgs) *(*int64)(ret) = *(*int64)(arguments[0]) + *(*int64)(arguments[1]) return 0 })
type Cif ¶
Cif stands for "Call InterFace". It describes the signature of a function.
Use PrepCif to initialize it.
type Closure ¶ added in v0.3.0
type Closure struct { Tramp [TrampolineSize]byte Cif *Cif Fun unsafe.Pointer UserData unsafe.Pointer }
Closure can be used to create callbacks (function pointers) at runtime.
Use ClosureAlloc for allocation and PrepClosureLoc for preparation.
func ClosureAlloc ¶ added in v0.3.0
ClosureAlloc allocates a new Closure.
- size should be big enough to hold a Closure object.
- code is the corresponding executable address (function pointer).
The Closure is not managed by Go's garbage collector. It can be deallocated by using ClosureFree.
Example:
var code unsafe.Pointer closure := ffi.ClosureAlloc(unsafe.Sizeof(ffi.Closure{}), &code) defer ffi.ClosureFree(closure)
type Fun ¶ added in v0.3.0
Fun is used to group a function's address and the related call interface together.
You can use Lib.Prep or Lib.PrepVar to create one.
func (Fun) Call ¶ added in v0.3.0
Call calls the function's address according to the description given in Cif.
- ret is a pointer to a variable that will hold the result of the function call. Provide nil if the function has no return value. You cannot use integer types smaller than 8 bytes here (float32 and structs are not affected). Use Arg instead and typecast afterwards.
- args are pointers to the argument values. Leave empty or provide nil if the function takes none.
Example:
// C function: // int ilogb(double x); var result ffi.Arg x := 1.0 ilogb.Call(&result, &x) fmt.Printf("%d\n", int32(result))
type Lib ¶ added in v0.3.0
type Lib struct {
Addr uintptr
}
Lib holds the address to a shared library.
Use Load to initialize one.
func Load ¶ added in v0.3.0
Load loads a shared library at runtime.
The name can be an absolute path, relative path or just the filename. If just the filename is passed, it will use the OS specific search paths.
Example:
var filename string switch runtime.GOOS { case "freebsd", "linux": filename = "libraylib.so" case "windows": filename = "raylib.dll" case "darwin": filename = "libraylib.dylib" } raylib, err := Load(filename)
func (Lib) Close ¶ added in v0.3.0
Close deletes a reference to the library. If the reference count is zero, the library gets unloaded.
func (Lib) Get ¶ added in v0.3.0
Get retrieves the address of an exported function or variable.
Example:
// C code: // int magic_number = 42; magicNumber, err := lib.Get("magic_number") if err != nil { panic(err) } // prints 42 fmt.Println(*(*int32)(unsafe.Pointer(magicNumber))) // if go vet yells "possible misuse of unsafe.Pointer", // you can do the following workaround: fmt.Println(**(**int32)(unsafe.Pointer(&magicNumber)))
func (Lib) Prep ¶ added in v0.3.0
Prep is used to get and describe a library's function.
- name is the name of the function.
- ret is the return type. Use TypeVoid if the function has none.
- args are the arguments. Leave empty or provide nil if the function has none.
For variadic functions use Lib.PrepVar instead.
Example:
// C function: // double cos(double x); cos, err := libm.Prep("cos", &ffi.TypeDouble, &ffi.TypeDouble) if err != nil { panic(err) }
func (Lib) PrepVar ¶ added in v0.3.0
PrepVar is used to get and describe a variadic function.
In general its operation is the same as for Lib.Prep except that:
- nFixedArgs is the number of fixed arguments, prior to any variadic arguments. It must be greater than zero.
This function will return an error if any of the variable argument types is TypeFloat. Same goes for integer types smaller than 4 bytes. See issue 608.
Note that, different cif's must be prepped for calls to the same function when different numbers of arguments are passed.
Also note that a call to this function with nFixedArgs = len(args) is NOT equivalent to a call to Lib.Prep.
Example:
// C function: // int printf(const char *restrict format, ...); printf, err := libc.PrepVar("printf", 1, &ffi.TypeSint32, &ffi.TypePointer, &ffi.TypeDouble) if err != nil { panic(err) } text, _ := unix.BytePtrFromString("Pi is %f\n") pi := math.Pi var nCharsPrinted int32 printf.Call(&nCharsPrinted, &text, &pi)
type Status ¶
type Status uint32
func PrepCif ¶
PrepCif initializes cif.
- abi is the ABI to use. Normally DefaultAbi is what you want.
- nArgs is the number of arguments. Use 0 if the function has none.
- rType is the return type. Use TypeVoid if the function has none.
- aTypes are the arguments. Leave empty or provide nil if the function has none.
The returned status code will be OK, if everything worked properly.
Example:
// C function: // double cos(double x); var cif ffi.Cif status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, &ffi.TypeDouble, &ffi.TypeDouble) if status != ffi.OK { panic(status) }
func PrepCifVar ¶
func PrepCifVar(cif *Cif, abi Abi, nFixedArgs, nTotalArgs uint32, rType *Type, aTypes ...*Type) Status
PrepCifVar initializes cif for a call to a variadic function.
In general its operation is the same as for PrepCif except that:
- nFixedArgs is the number of fixed arguments, prior to any variadic arguments. It must be greater than zero.
- nTotalArgs is the total number of arguments, including variadic and fixed arguments. aTypes must have this many elements.
This function will return BadArgType if any of the variable argument types is TypeFloat. Same goes for integer types smaller than 4 bytes. See issue 608.
Note that, different cif's must be prepped for calls to the same function when different numbers of arguments are passed.
Also note that a call to this function with nFixedArgs = nTotalArgs is NOT equivalent to a call to PrepCif.
Example:
// C function: // int printf(const char *restrict format, ...); var cif ffi.Cif status := ffi.PrepCifVar(&cif, ffi.DefaultAbi, 1, 2, &ffi.TypeSint32, &ffi.TypePointer, &ffi.TypeDouble) if status != ffi.OK { panic(status) } text, _ := unix.BytePtrFromString("Pi is %f\n") pi := math.Pi var nCharsPrinted int32 ffi.Call(&cif, printf, unsafe.Pointer(&nCharsPrinted), unsafe.Pointer(&text), unsafe.Pointer(&pi))
func PrepClosureLoc ¶ added in v0.3.0
func PrepClosureLoc(closure *Closure, cif *Cif, fun uintptr, userData, codeLoc unsafe.Pointer) Status
PrepClosureLoc creates a C function (so-called closure) at runtime.
- closure is the object return by ClosureAlloc.
- cif describes the signature of the function to be created. Use PrepCif for initialization.
- fun is a pointer to a C function which will be called when the closure is invoked. You can use NewCallback to create one.
- userData is arbitrary and optional (can be nil) data passed to your closure function fun.
- codeLoc is the executable address allocated by ClosureAlloc.
Example ¶
package main import ( "fmt" "math" "unsafe" "github.com/jupiterrider/ffi" ) func main() { var sin unsafe.Pointer closure := ffi.ClosureAlloc(unsafe.Sizeof(ffi.Closure{}), &sin) defer ffi.ClosureFree(closure) fun := ffi.NewCallback(func(cif *ffi.Cif, ret unsafe.Pointer, args *unsafe.Pointer, userData unsafe.Pointer) uintptr { arg := unsafe.Slice(args, cif.NArgs)[0] sine := math.Sin(*(*float64)(arg)) *(*float64)(ret) = sine return 0 }) var cif ffi.Cif if status := ffi.PrepCif(&cif, ffi.DefaultAbi, 1, &ffi.TypeDouble, &ffi.TypeDouble); status != ffi.OK { panic(status) } if status := ffi.PrepClosureLoc(closure, &cif, fun, nil, sin); status != ffi.OK { panic(status) } var sine float64 var x float64 = 1 ffi.Call(&cif, uintptr(sin), unsafe.Pointer(&sine), unsafe.Pointer(&x)) fmt.Println(sine) }
Output: 0.8414709848078965
type Type ¶
type Type struct { Size uint64 // Initialize to 0 (automatically set by libffi as needed). Alignment uint16 // Initialize to 0 (automatically set by libffi as needed). Type uint16 // Use ffi.Struct for struct types. Elements **Type // Pointer to the first element of a nil-terminated slice. }
Type is used to describe the structure of a data type.
Example:
// C struct: // typedef struct Point { // int x; // int y; // } Point; typePoint := ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeSint32, &ffi.TypeSint32, nil}[0]}
Primitive data types are already defined (e.g. TypeDouble for float64).