Skip to content

Commit

Permalink
Add lifetime helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
csnewman committed Dec 9, 2024
1 parent 2164e59 commit d432422
Showing 1 changed file with 67 additions and 0 deletions.
67 changes: 67 additions & 0 deletions goblend.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,77 @@ import (
//go:linkname runtime_cgocall runtime.cgocall
func runtime_cgocall(fn uintptr, arg uintptr) int32

// Call invokes the native function, passing a single argument.
//
// It is important that any pointers referenced from arg are alive and are valid throughout the duration of their use.
//
// [KeepAliveSpill] is the preferred choice for keeping pointers alive. It will cause the value to be stored on the
// meaning that the native code is allowed to perform Go callbacks or store the pointer (assuming the memory has been
// pinned with [runtime.Pinner]).
//
// [KeepAliveNoSpill] can be used in limited circumstance, where the function does not call Go code or attempt to store
// the value.
func Call(fn uintptr, arg uintptr) int32 {
return runtime_cgocall(fn, arg)
}

// FuncPtr returns the address of the provided function, suitable for passing to native code.
func FuncPtr(f any) uintptr {
return reflect.ValueOf(f).Pointer()
}

// AlwaysFalse is always false.
//
// This value is hidden from the compiler, so code using it will not be eliminated.
//
//go:linkname AlwaysFalse runtime.cgoAlwaysFalse
var AlwaysFalse bool

//go:linkname runtime_cgo_use runtime.cgoUse
func runtime_cgo_use(interface{})

// TODO: replace runtime_cgo_use_noescape with runtime.cgoKeepAlive in Go 1.24.

// TODO: expose no callback helpers in Go 1.24.

//go:linkname runtime_cgo_use_noescape runtime.cgoUse
//go:noescape
func runtime_cgo_use_noescape(interface{})

// KeepAliveSpill will keep the value alive until this point and will cause the value to be stored on the heap.
func KeepAliveSpill(v any) {
if AlwaysFalse {
runtime_cgo_use(v)
}
}

// KeepAliveNoSpill will keep the value alive until this point without causing the value to be stored on the heap.
func KeepAliveNoSpill(v any) {
if AlwaysFalse {
runtime_cgo_use_noescape(v)
}
}

//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
//go:noescape
func _cgoCheckPointer(any, any)

// CheckPointer checks if the argument contains a Go pointer that points to an unpinned Go pointer, and panics if it
// does. See [runtime.cgoCheckPointer] for more details.
//
// NOTE: This may not yet be working.
func CheckPointer(ptr any, arg any) {
_cgoCheckPointer(ptr, arg)
}

//go:linkname _cgoCheckResult runtime.cgoCheckResult
//go:noescape
func _cgoCheckResult(any)

// CheckResult checks the result parameter of an exported Go function. It panics if the result is or contains any other
// pointer into unpinned Go memory. See [runtime.cgoCheckResult] for more details.
//
// NOTE: This may not yet be working.
func CheckResult(ptr any) {
_cgoCheckResult(ptr)
}

0 comments on commit d432422

Please sign in to comment.