New upstream version 0.0~git20180825.49522c3
Drew Parsons
5 years ago
|
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
|
|
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 |
}
|