Documentation
¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewCallback ¶
func NewCallback(fn interface{}) uintptr
NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. This is useful when interoperating with Windows code requiring callbacks. The argument is expected to be a function with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated for these callbacks is never released. Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created. Although this function is similiar to the darwin version it may act differently.
Example ¶
package main
import (
"fmt"
"runtime"
"github.com/ebitengine/purego"
)
func main() {
if runtime.GOOS == "linux" {
// TODO: enable once callbacks are working properly on Linux
fmt.Println("1 2 3 4 5 6 7 8 9\n45")
return
}
cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int) int {
fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9)
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9
})
var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int) int
purego.RegisterFunc(&fn, cb)
ret := fn(1, 2, 3, 4, 5, 6, 7, 8, 9)
fmt.Println(ret)
}
Output: 1 2 3 4 5 6 7 8 9 45
func RegisterFunc ¶ added in v0.4.0
func RegisterFunc(fptr interface{}, cfn uintptr)
RegisterFunc takes a pointer to a Go function representing the calling convention of the C function. fptr will be set to a function that when called will call the C function given by cfn with the parameters passed in the correct registers and stack.
A panic is produced if the type is not a function pointer or if the function returns more than 1 value.
These conversions describe how a Go type in the fptr will be used to call the C function. It is important to note that there is no way to verify that fptr matches the C function. This also holds true for struct types where the padding needs to be ensured to match that of C; RegisterFunc does not verify this.
Type Conversions (Go => C)
string <=> char* bool <=> _Bool uintptr <=> uintptr_t uint <=> uint32_t or uint64_t uint8 <=> uint8_t uint16 <=> uint16_t uint32 <=> uint32_t uint64 <=> uint64_t int <=> int32_t or int64_t int8 <=> int8_t int16 <=> int16_t int32 <=> int32_t int64 <=> int64_t float32 <=> float (WIP) float64 <=> double (WIP) struct <=> struct (WIP) func <=> C function unsafe.Pointer, *T <=> void* []T => void*
There is a special case when the last argument of fptr is a variadic interface (or []interface} it will be expanded into a call to the C function as if it had the arguments in that slice. This means that using arg ...interface{} is like a cast to the function with the arguments inside arg. This is not the same as C variadic.
There are some limitations when using RegisterFunc on Linux. First, there is no support for function arguments. Second, float32 and float64 arguments and return values do not work when CGO_ENABLED=1. Otherwise, Linux has the same feature parity as Darwin.
func RegisterLibFunc ¶ added in v0.4.0
RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name). It panics if it can't find the name symbol.
func SyscallN ¶
SyscallN takes fn, a C function pointer and a list of arguments as uintptr. There is an internal maximum number of arguments that SyscallN can take. It panics when the maximum is exceeded. It returns the result and the libc error code if there is one.
NOTE: SyscallN does not properly call functions that have both integer and float parameters. See discussion comment https://github.com/ebiten/purego/pull/1#issuecomment-1128057607 for an explanation of why that is.
On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the stack.
The pragma go:nosplit is not needed at this function declaration because it uses go:uintptrescapes which forces all the objects that the uintptrs point to onto the heap where a stack split won't affect their memory location.
Types ¶
This section is empty.