...

Source file src/runtime/cgo/handle.go

Documentation: runtime/cgo

		 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.
		 4  
		 5  package cgo
		 6  
		 7  import (
		 8  	"sync"
		 9  	"sync/atomic"
		10  )
		11  
		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.
		18  //
		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
		22  // in C APIs.
		23  //
		24  // For instance, on the Go side:
		25  //
		26  //	package main
		27  //
		28  //	/*
		29  //	#include <stdint.h> // for uintptr_t
		30  //
		31  //	extern void MyGoPrint(uintptr_t handle);
		32  //	void myprint(uintptr_t handle);
		33  //	*/
		34  //	import "C"
		35  //	import "runtime/cgo"
		36  //
		37  //	//export MyGoPrint
		38  //	func MyGoPrint(handle C.uintptr_t) {
		39  //		h := cgo.Handle(handle)
		40  //		val := h.Value().(string)
		41  //		println(val)
		42  //		h.Delete()
		43  //	}
		44  //
		45  //	func main() {
		46  //		val := "hello Go"
		47  //		C.myprint(C.uintptr_t(cgo.NewHandle(val)))
		48  //		// Output: hello Go
		49  //	}
		50  //
		51  // and on the C side:
		52  //
		53  //	#include <stdint.h> // for uintptr_t
		54  //
		55  //	// A Go function
		56  //	extern void MyGoPrint(uintptr_t handle);
		57  //
		58  //	// A C function
		59  //	void myprint(uintptr_t handle) {
		60  //			MyGoPrint(handle);
		61  //	}
		62  type Handle uintptr
		63  
		64  // NewHandle returns a handle for a given value.
		65  //
		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.
		70  //
		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)
		75  	if h == 0 {
		76  		panic("runtime/cgo: ran out of handle space")
		77  	}
		78  
		79  	handles.Store(h, v)
		80  	return Handle(h)
		81  }
		82  
		83  // Value returns the associated Go value for a valid handle.
		84  //
		85  // The method panics if the handle is invalid.
		86  func (h Handle) Value() interface{} {
		87  	v, ok := handles.Load(uintptr(h))
		88  	if !ok {
		89  		panic("runtime/cgo: misuse of an invalid Handle")
		90  	}
		91  	return v
		92  }
		93  
		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.
		97  //
		98  // The method panics if the handle is invalid.
		99  func (h Handle) Delete() {
	 100  	_, ok := handles.LoadAndDelete(uintptr(h))
	 101  	if !ok {
	 102  		panic("runtime/cgo: misuse of an invalid Handle")
	 103  	}
	 104  }
	 105  
	 106  var (
	 107  	handles	 = sync.Map{} // map[Handle]interface{}
	 108  	handleIdx uintptr			// atomic
	 109  )
	 110  

View as plain text