diff options
author | Ian Lance Taylor <iant@golang.org> | 2015-02-22 11:09:58 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2015-02-22 11:09:58 -0800 |
commit | 1dd401899fc230073295cf86db4a5d66eefdba85 (patch) | |
tree | e60a664b0a1713c99614e9c2238b5294ab62a3e2 /Lib/go | |
parent | 40f5b1ecc684d092bbceff319c62fda84fab1bc6 (diff) | |
download | swig-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.swg | 55 |
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) +} + +%} |