@@ -14,9 +14,9 @@ import (
1414 "sync"
1515)
1616
17- // Handle provides a safe representation to communicate Go values between
18- // C and Go . The zero value of a handle is not a valid handle, and thus
19- // safe to use as a sentinel in C APIs.
17+ // Handle provides a safe representation to pass Go values between C and
18+ // Go back and forth . The zero value of a handle is not a valid handle,
19+ // and thus safe to use as a sentinel in C APIs.
2020//
2121// The underlying type of Handle may change, but the value is guaranteed
2222// to fit in an integer type that is large enough to hold the bit pattern
@@ -25,14 +25,14 @@ import (
2525// package main
2626//
2727// /*
28- // extern void GoPrint (unsigned long long handle);
29- // void printFromGo (unsigned long long handle);
28+ // extern void MyGoPrint (unsigned long long handle);
29+ // void myprint (unsigned long long handle);
3030// */
3131// import "C"
3232// import "runtime/cgo"
3333//
34- // //export GoPrint
35- // func GoPrint (handle C.ulonglong) {
34+ // //export MyGoPrint
35+ // func MyGoPrint (handle C.ulonglong) {
3636// h := cgo.Handle(handle)
3737// val := h.Value().(int)
3838// println(val)
@@ -41,18 +41,18 @@ import (
4141//
4242// func main() {
4343// val := 42
44- //
45- // C.printFromGo(C.ulonglong(cgo.NewHandle(val))) // prints 42
44+ // C.myprint(C.ulonglong(cgo.NewHandle(val)))
45+ // // Output: 42
4646// }
4747//
4848// and on the C side:
4949//
50- // // This function is from Go side.
51- // extern void GoPrint (unsigned long long handle);
50+ // // A Go function
51+ // extern void MyGoPrint (unsigned long long handle);
5252//
5353// // A C function
54- // void printFromGo (unsigned long long handle) {
55- // GoPrint (handle);
54+ // void myprint (unsigned long long handle) {
55+ // MyGoPrint (handle);
5656// }
5757type Handle uintptr
5858
@@ -77,23 +77,29 @@ func NewHandle(v interface{}) Handle {
7777 case reflect .Ptr , reflect .UnsafePointer , reflect .Slice ,
7878 reflect .Map , reflect .Chan , reflect .Func :
7979 if rv .IsNil () {
80- panic ("cannot use handle for nil value" )
80+ panic ("cgo: cannot use Handle for nil value" )
8181 }
8282
8383 k = rv .Pointer ()
8484 default :
85- k = reflect .ValueOf (& v ).Pointer ()
85+ // Wrap and turn a value parameter into a pointer. This enables
86+ // us to always store the passing object as a pointer, and helps
87+ // to identify which of whose are initially pointers or values
88+ // when Value is called.
89+ v = & wrap {v }
90+ k = reflect .ValueOf (v ).Pointer ()
8691 }
8792
88- // v escapes to the heap, always . As Go do not have a moving GC (and
89- // possibly lasts true for a long future), it is safe to use its
90- // pointer address as the key of the global map at this moment.
91- // The implementation must be reconsidered if moving GC is
92- // introduced internally.
93+ // v was escaped to the heap because of reflection . As Go do not have
94+ // a moving GC (and possibly lasts true for a long future), it is
95+ // safe to use its pointer address as the key of the global map at
96+ // this moment. The implementation must be reconsidered if moving GC
97+ // is introduced internally in the runtime .
9398 actual , loaded := m .LoadOrStore (k , v )
9499 if ! loaded {
95100 return Handle (k )
96101 }
102+
97103 arv := reflect .ValueOf (actual )
98104 switch arv .Kind () {
99105 case reflect .Ptr , reflect .UnsafePointer , reflect .Slice ,
@@ -104,16 +110,15 @@ func NewHandle(v interface{}) Handle {
104110 return Handle (k )
105111 }
106112
107- // If the loaded actual value is inconsistent with the new
108- // value, it means the address has been used for different
109- // objects, and we should fallthrough, see comments below.
110- fallthrough
113+ // If the loaded pointer is inconsistent with the new pointer,
114+ // it means the address has been used for different objects
115+ // because of GC and its address is reused for a new Go object,
116+ // meaning that the Handle does not call Delete explicitly when
117+ // the old Go value is not needed. Consider this as a misuse of
118+ // a handle, do panic.
119+ panic ("cgo: misuse of a Handle" )
111120 default :
112- // If a Go value is garbage collected and its address is reused
113- // for a new Go value, meaning that the Handle does not call
114- // Delete explicitly when the old Go value is not needed.
115- // Consider this as a misuse of a handle, do panic.
116- panic ("misuse of a handle" )
121+ panic ("cgo: Handle implementation has an internal bug" )
117122 }
118123}
119124
@@ -125,7 +130,7 @@ func NewHandle(v interface{}) Handle {
125130func (h Handle ) Delete () {
126131 _ , ok := m .LoadAndDelete (uintptr (h ))
127132 if ! ok {
128- panic ("misuse of a handle " )
133+ panic ("cgo: misuse of an invalid Handle " )
129134 }
130135}
131136
@@ -135,9 +140,17 @@ func (h Handle) Delete() {
135140func (h Handle ) Value () interface {} {
136141 v , ok := m .Load (uintptr (h ))
137142 if ! ok {
138- panic ("misuse of a handle" )
143+ panic ("cgo: misuse of an invalid Handle" )
144+ }
145+ if wv , ok := v .(* wrap ); ok {
146+ return wv .v
139147 }
140148 return v
141149}
142150
143151var m = & sync.Map {} // map[uintptr]interface{}
152+
153+ // wrap wraps a Go value.
154+ type wrap struct {
155+ v interface {}
156+ }
0 commit comments