blob: 5fb8642d4cb50ff0efef868a261e2a591973ac50 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
package backend
import (
"fmt"
"reflect"
"sync"
"unsafe"
)
/* ATCHUNG! what follow are not silly comments. Well, *this one* is, but
the lines after this are not.
Those are inline C functions, that are invoked by CGO later on.
it's also crucial that you don't any extra space between the function
block and the 'import "C"' line. */
// typedef void (*cb)();
// inline void _do_callback(cb f) {
// f();
// }
import "C"
/* callbacks into C-land. We keep a registry, and protect its updates with a mutex. */
var callbacks = make(map[string](*[0]byte))
var callbackMutex sync.Mutex
var initOnce sync.Once
// Events are just a enumeration of all the posible events that C functions can
// be interested in subscribing to. You cannot subscribe to an event that is
// not listed here.
type Events struct {
OnStatusChanged string
}
const OnStatusChanged string = "OnStatusChanged"
// subscribe registers a callback from C-land.
// This callback needs to be passed as a void* C function pointer.
func subscribe(event string, fp unsafe.Pointer) {
callbackMutex.Lock()
defer callbackMutex.Unlock()
e := &Events{}
v := reflect.Indirect(reflect.ValueOf(&e))
hf := v.Elem().FieldByName(event)
if reflect.ValueOf(hf).IsZero() {
fmt.Println("ERROR: not a valid event:", event)
} else {
callbacks[event] = (*[0]byte)(fp)
}
}
// trigger fires a callback from C-land.
func trigger(event string) {
callbackMutex.Lock()
defer callbackMutex.Unlock()
cb := callbacks[event]
if cb != nil {
C._do_callback(cb)
} else {
fmt.Println("ERROR: this event does not have subscribers:", event)
}
}
|