1 // Copyright 2021 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 // Handle provides a way to pass values that contain Go pointers
13 // (pointers to memory allocated by Go) between Go and C without
14 // breaking the cgo pointer passing rules. A Handle is an integer
15 // value that can represent any Go value. A Handle can be passed
16 // through C and back to Go, and Go code can use the Handle to
17 // retrieve the original Go value.
19 // The underlying type of Handle is guaranteed to fit in an integer type
20 // that is large enough to hold the bit pattern of any pointer. The zero
21 // value of a Handle is not valid, and thus is safe to use as a sentinel
24 // For instance, on the Go side:
29 // #include <stdint.h> // for uintptr_t
31 // extern void MyGoPrint(uintptr_t handle);
32 // void myprint(uintptr_t handle);
35 // import "runtime/cgo"
38 // func MyGoPrint(handle C.uintptr_t) {
39 // h := cgo.Handle(handle)
40 // val := h.Value().(string)
47 // C.myprint(C.uintptr_t(cgo.NewHandle(val)))
48 // // Output: hello Go
53 // #include <stdint.h> // for uintptr_t
56 // extern void MyGoPrint(uintptr_t handle);
59 // void myprint(uintptr_t handle) {
64 // NewHandle returns a handle for a given value.
66 // The handle is valid until the program calls Delete on it. The handle
67 // uses resources, and this package assumes that C code may hold on to
68 // the handle, so a program must explicitly call Delete when the handle
69 // is no longer needed.
71 // The intended use is to pass the returned handle to C code, which
72 // passes it back to Go, which calls Value.
73 func NewHandle(v interface{}) Handle {
74 h := atomic.AddUintptr(&handleIdx, 1)
76 panic("runtime/cgo: ran out of handle space")
83 // Value returns the associated Go value for a valid handle.
85 // The method panics if the handle is invalid.
86 func (h Handle) Value() interface{} {
87 v, ok := handles.Load(uintptr(h))
89 panic("runtime/cgo: misuse of an invalid Handle")
94 // Delete invalidates a handle. This method should only be called once
95 // the program no longer needs to pass the handle to C and the C code
96 // no longer has a copy of the handle value.
98 // The method panics if the handle is invalid.
99 func (h Handle) Delete() {
100 _, ok := handles.LoadAndDelete(uintptr(h))
102 panic("runtime/cgo: misuse of an invalid Handle")
107 handles = sync.Map{} // map[Handle]interface{}
108 handleIdx uintptr // atomic