]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/runtime/cgo/handle.go
runtime: add available godoc link
[gostls13.git] / src / runtime / cgo / handle.go
index 720acca802c882c3b9877132ce0616c13c68b1d3..59b65da2b6d763aeb8d153ed4ebd7384964f37db 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.
@@ -70,8 +105,8 @@ type Handle uintptr
 //
 // The intended use is to pass the returned handle to C code, which
 // passes it back to Go, which calls Value.
-func NewHandle(v interface{}) Handle {
-       h := atomic.AddUintptr(&handleIdx, 1)
+func NewHandle(v any) Handle {
+       h := handleIdx.Add(1)
        if h == 0 {
                panic("runtime/cgo: ran out of handle space")
        }
@@ -83,7 +118,7 @@ func NewHandle(v interface{}) Handle {
 // Value returns the associated Go value for a valid handle.
 //
 // The method panics if the handle is invalid.
-func (h Handle) Value() interface{} {
+func (h Handle) Value() any {
        v, ok := handles.Load(uintptr(h))
        if !ok {
                panic("runtime/cgo: misuse of an invalid Handle")
@@ -105,5 +140,5 @@ func (h Handle) Delete() {
 
 var (
        handles   = sync.Map{} // map[Handle]interface{}
-       handleIdx uintptr      // atomic
+       handleIdx atomic.Uintptr
 )