-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
In go1.6, cgo rules regarding the passing of Go pointers to C libraries changed to prevent unsafe interactions with the Go garbage collector. We need to change so that we pass an indirect reference to the Go object to the c-runtime. This code has been tested to the extent that required to address the particular panic reported with #4 However, a more extensive regression test has not yet been performed. Signed-off-by: Jon Seymour <[email protected]>
- Loading branch information
Jon Seymour
committed
Mar 26, 2016
1 parent
e77291c
commit 03d83af
Showing
6 changed files
with
96 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
typedef struct shareable { | ||
int sharedIndex; | ||
} shareable; | ||
|
||
shareable * newShareable(int i); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#include "api.h" | ||
|
||
shareable * newShareable(int i) { | ||
shareable * r = (shareable *) malloc(sizeof(shareable)); | ||
r->sharedIndex = i; | ||
return r; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package openzwave | ||
|
||
// #cgo LDFLAGS: -lopenzwave -Lgo/src/github.com/ninjasphere/go-openzwave/openzwave | ||
// #cgo CPPFLAGS: -Iopenzwave/cpp/src/platform -Iopenzwave/cpp/src -Iopenzwave/cpp/src/value_classes | ||
// #include "api.h" | ||
import "C" | ||
|
||
import ( | ||
"fmt" | ||
"unsafe" | ||
) | ||
|
||
// This module works around an issue revealed when Go 1.6 tightened up the rules | ||
// about sharing of Go pointers with C code. https://github.com/golang/go/issues/12416 | ||
// | ||
// Now we register a reference with a map and get an integer in return. We use | ||
// this integer to map back into the Go world. | ||
|
||
type Shareable interface { | ||
GetSharingIndex() int | ||
SetSharingIndex(int) | ||
GetShareable() unsafe.Pointer | ||
} | ||
|
||
type shareable struct { | ||
cref *C.shareable | ||
} | ||
|
||
func (s *shareable) GetSharingIndex() int { | ||
if s.cref == nil { | ||
return 0 | ||
} else { | ||
return int(s.cref.sharedIndex) | ||
} | ||
} | ||
|
||
func (s *shareable) SetSharingIndex(i int) { | ||
if i == 0 { | ||
C.free(s.cref) | ||
s.cref = nil | ||
} else if s.cref == nil { | ||
s.cref = C.newShareable(C.int(i)) | ||
} | ||
s.cref.sharedIndex = C.int(i) | ||
} | ||
|
||
func (s *shareable) GetShareable() unsafe.Pointer { | ||
return unsafe.Pointer(s.cref) | ||
} | ||
|
||
var shared = map[int]Shareable{} | ||
var sharedCount = 0 | ||
|
||
func marshal(p Shareable) unsafe.Pointer { | ||
if p.GetSharingIndex() == 0 { | ||
sharedCount++ | ||
p.SetSharingIndex(sharedCount) | ||
shared[sharedCount] = p | ||
} | ||
return p.GetShareable() | ||
} | ||
|
||
func unmarshal(c unsafe.Pointer) Shareable { | ||
i := (*C.shareable)(c).sharedIndex | ||
if i == 0 { | ||
return nil | ||
} else { | ||
if s, ok := shared[int(i)]; !ok { | ||
panic(fmt.Errorf("failure to unmarshal index %d", int(i))) | ||
} else { | ||
return s | ||
} | ||
} | ||
} | ||
|
||
func release(i int) { | ||
delete(shared, i) | ||
} |