summaryrefslogtreecommitdiff
path: root/Lib/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2015-02-22 11:09:58 -0800
committerIan Lance Taylor <iant@golang.org>2015-02-22 11:09:58 -0800
commit1dd401899fc230073295cf86db4a5d66eefdba85 (patch)
treee60a664b0a1713c99614e9c2238b5294ab62a3e2 /Lib/go
parent40f5b1ecc684d092bbceff319c62fda84fab1bc6 (diff)
downloadswig-1dd401899fc230073295cf86db4a5d66eefdba85.tar.gz
[Go] Change SWIG directors to use a handle instead of a Go pointer.
In future releases of Go it will not be possible to pass Go pointers into C/C++ code. The handle is automatically translated back to the Go value using a Go map. Since directors must be explicitly deleted, we can reliably use that call to remove the handle from the map.
Diffstat (limited to 'Lib/go')
-rw-r--r--Lib/go/goruntime.swg55
1 files changed, 55 insertions, 0 deletions
diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg
index 19ccf5ae9..f76da9c78 100644
--- a/Lib/go/goruntime.swg
+++ b/Lib/go/goruntime.swg
@@ -317,3 +317,58 @@ static void swig_acquire_pointer(Swig_memory** pmem, Type* ptr) {
(*pmem)->swig_acquire_pointer(ptr);
}
%}
+
+/* For directors we need C++ to track a Go pointer. Since we can't
+ pass a Go pointer into C++, we use a map to track the pointers on
+ the Go side. */
+
+%go_import("sync")
+
+%insert(go_header) %{
+type _ sync.Mutex
+%}
+
+%insert(go_director) %{
+
+var swigDirectorTrack struct {
+ sync.Mutex
+ m map[int]interface{}
+ c int
+}
+
+func swigDirectorAdd(v interface{}) int {
+ swigDirectorTrack.Lock()
+ defer swigDirectorTrack.Unlock()
+ if swigDirectorTrack.m == nil {
+ swigDirectorTrack.m = make(map[int]interface{})
+ }
+ swigDirectorTrack.c++
+ ret := swigDirectorTrack.c
+ swigDirectorTrack.m[ret] = v
+ return ret
+}
+
+func swigDirectorLookup(c int) interface{} {
+ swigDirectorTrack.Lock()
+ defer swigDirectorTrack.Unlock()
+ ret := swigDirectorTrack.m[c]
+ if ret == nil {
+ panic("C++ director pointer not found (possible use-after-free)")
+ }
+ return ret
+}
+
+func swigDirectorDelete(c int) {
+ swigDirectorTrack.Lock()
+ defer swigDirectorTrack.Unlock()
+ if swigDirectorTrack.m[c] == nil {
+ if c > swigDirectorTrack.c {
+ panic("C++ director pointer invalid (possible memory corruption")
+ } else {
+ panic("C++ director pointer not found (possible use-after-free)")
+ }
+ }
+ delete(swigDirectorTrack.m, c)
+}
+
+%}