]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: add example of Handle with void* parameter
authorAlan Donovan <alan@alandonovan.net>
Wed, 17 Nov 2021 17:54:22 +0000 (12:54 -0500)
committerIan Lance Taylor <iant@golang.org>
Sat, 20 Nov 2021 00:37:28 +0000 (00:37 +0000)
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>

misc/cgo/test/cgo_test.go
misc/cgo/test/test.go
misc/cgo/test/testx.go
src/runtime/cgo/handle.go

index fe99e251e96bb40c59af980a298a126e03cb811b..774277e10da6a080cfa9040f11ac5692459d5e9d 100644 (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) }
index 3b8f548b13dd206fedd0653d8472c5b8d9958d12..dd81f770a2070c299a8ca4343bcd3dacb0ff0f8c 100644 (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"
 
index 823c3e13d2927aac7bfd240ddd46b69882a8aff0..a61b47c41d87548ba88c577f17d4fbfc4013f5ec 100644 (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)
+       }
+}
index 720acca802c882c3b9877132ce0616c13c68b1d3..726f0a396d19c88cb7dcf3a1eae2385bdbbc5189 100644 (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.