[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.
This commit is contained in:
Ian Lance Taylor 2015-02-22 11:09:58 -08:00
commit 1dd401899f
2 changed files with 81 additions and 13 deletions

View file

@ -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)
}
%}