Codebase list golang-github-mattn-go-pointer / 986d356
New upstream version 0.0~git20180825.49522c3 Drew Parsons 5 years ago
5 changed file(s) with 125 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 # go-pointer
1
2 Utility for cgo
3
4 ## Usage
5
6 https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md
7
8 In go 1.6, cgo argument can't be passed Go pointer.
9
10 ```
11 var s string
12 C.pass_pointer(pointer.Save(&s))
13 v := *(pointer.Restore(C.get_from_pointer()).(*string))
14 ```
15
16 ## Installation
17
18 ```
19 go get github.com/mattn/go-pointer
20 ```
21
22 ## License
23
24 MIT
25
26 ## Author
27
28 Yasuhiro Matsumoto (a.k.a mattn)
0 #include <unistd.h>
1
2 typedef void (*callback)(void*);
3
4 static void call_later(int delay, callback cb, void* data) {
5 sleep(delay);
6 cb(data);
7 }
8
0 package main
1
2 /*
3 #include "callback.h"
4
5 void call_later_go_cb(void*);
6 */
7 import "C"
8 import (
9 "fmt"
10 "unsafe"
11
12 "github.com/mattn/go-pointer"
13 )
14
15 type Foo struct {
16 v int
17 }
18
19 func main() {
20 f := &Foo{123}
21 C.call_later(3, C.callback(C.call_later_go_cb), pointer.Save(f))
22 }
23
24 //export call_later_go_cb
25 func call_later_go_cb(data unsafe.Pointer) {
26 f := pointer.Restore(data).(*Foo)
27 fmt.Println(f.v)
28 }
0 package pointer
0 package pointer
1
2 // #include <stdlib.h>
3 import "C"
4 import (
5 "sync"
6 "unsafe"
7 )
8
9 var (
10 mutex sync.Mutex
11 store = map[unsafe.Pointer]interface{}{}
12 )
13
14 func Save(v interface{}) unsafe.Pointer {
15 if v == nil {
16 return nil
17 }
18
19 // Generate real fake C pointer.
20 // This pointer will not store any data, but will bi used for indexing purposes.
21 // Since Go doest allow to cast dangling pointer to unsafe.Pointer, we do rally allocate one byte.
22 // Why we need indexing, because Go doest allow C code to store pointers to Go data.
23 var ptr unsafe.Pointer = C.malloc(C.size_t(1))
24 if ptr == nil {
25 panic("can't allocate 'cgo-pointer hack index pointer': ptr == nil")
26 }
27
28 mutex.Lock()
29 store[ptr] = v
30 mutex.Unlock()
31
32 return ptr
33 }
34
35 func Restore(ptr unsafe.Pointer) (v interface{}) {
36 if ptr == nil {
37 return nil
38 }
39
40 mutex.Lock()
41 v = store[ptr]
42 mutex.Unlock()
43 return
44 }
45
46 func Unref(ptr unsafe.Pointer) {
47 if ptr == nil {
48 return
49 }
50
51 mutex.Lock()
52 delete(store, ptr)
53 mutex.Unlock()
54
55 C.free(ptr)
56 }