runtime/cgo: add example of Handle with void* parameter

Fixes #49633

Change-Id: I12ca350f7dd6bfc8753a4a169f29b89ef219b035
Reviewed-on: https://go-review.googlesource.com/c/go/+/364774
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Alan Donovan 2021-11-17 12:54:22 -05:00 committed by Ian Lance Taylor
parent 57aba325c8
commit d2f4c935f2
4 changed files with 66 additions and 0 deletions

View file

@ -61,6 +61,7 @@ func Test32579(t *testing.T) { test32579(t) }
func Test31891(t *testing.T) { test31891(t) }
func Test42018(t *testing.T) { test42018(t) }
func Test45451(t *testing.T) { test45451(t) }
func Test49633(t *testing.T) { test49633(t) }
func TestAlign(t *testing.T) { testAlign(t) }
func TestAtol(t *testing.T) { testAtol(t) }
func TestBlocking(t *testing.T) { testBlocking(t) }

View file

@ -915,6 +915,11 @@ void issue40494(enum Enum40494 e, union Union40494* up) {}
// Issue 45451, bad handling of go:notinheap types.
typedef struct issue45451Undefined issue45451;
// Issue 49633, example of cgo.Handle with void*.
extern void GoFunc49633(void*);
void cfunc49633(void *context) { GoFunc49633(context); }
*/
import "C"

View file

@ -113,6 +113,8 @@ typedef struct {
int i;
} Issue38408, *PIssue38408;
extern void GoFunc49633(void *context);
extern void cfunc49633(void*); // definition is in test.go
*/
import "C"
@ -554,3 +556,26 @@ func GoFunc37033(handle C.uintptr_t) {
// A typedef pointer can be used as the element type.
// No runtime test; just make sure it compiles.
var _ C.PIssue38408 = &C.Issue38408{i: 1}
// issue 49633, example use of cgo.Handle with void*
type data49633 struct {
msg string
}
//export GoFunc49633
func GoFunc49633(context unsafe.Pointer) {
h := *(*cgo.Handle)(context)
v := h.Value().(*data49633)
v.msg = "hello"
}
func test49633(t *testing.T) {
v := &data49633{}
h := cgo.NewHandle(v)
defer h.Delete()
C.cfunc49633(unsafe.Pointer(&h))
if v.msg != "hello" {
t.Errorf("msg = %q, want 'hello'", v.msg)
}
}

View file

@ -59,6 +59,41 @@ import (
// void myprint(uintptr_t handle) {
// MyGoPrint(handle);
// }
//
// Some C functions accept a void* argument that points to an arbitrary
// data value supplied by the caller. It is not safe to coerce a cgo.Handle
// (an integer) to a Go unsafe.Pointer, but instead we can pass the address
// of the cgo.Handle to the void* parameter, as in this variant of the
// previous example:
//
// package main
//
// /*
// extern void MyGoPrint(void *context);
// static inline void myprint(void *context) {
// MyGoPrint(context);
// }
// */
// import "C"
// import (
// "runtime/cgo"
// "unsafe"
// )
//
// //export MyGoPrint
// func MyGoPrint(context unsafe.Pointer) {
// h := *(*cgo.Handle)(context)
// val := h.Value().(string)
// println(val)
// h.Delete()
// }
//
// func main() {
// val := "hello Go"
// h := cgo.NewHandle(val)
// C.myprint(unsafe.Pointer(&h))
// // Output: hello Go
// }
type Handle uintptr
// NewHandle returns a handle for a given value.