summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-02-16 16:43:48 -0500
committerPietro Gagliardi <[email protected]>2014-02-16 16:43:48 -0500
commit7a99d42d656b74e523fb89ef38b1402615c67570 (patch)
treea60d048001d4c5422b4b94d999b7bac6b9fce999
parentc40b7b5599236a8e85f7bf610bfaebd4a609da0a (diff)
Added cgo-safe callback code for GTK+ signals. GTK+ signals work!
-rw-r--r--callbacks_unix.go27
-rw-r--r--gtkcalls_unix.go24
-rw-r--r--sysdata_unix.go8
3 files changed, 37 insertions, 22 deletions
diff --git a/callbacks_unix.go b/callbacks_unix.go
new file mode 100644
index 0000000..d47d67d
--- /dev/null
+++ b/callbacks_unix.go
@@ -0,0 +1,27 @@
+// +build !windows,!darwin,!plan9
+
+// 16 february 2014
+package main
+
+import (
+ "unsafe"
+)
+
+/*
+cgo doesn't support calling Go functions by default; we have to mark them for export. Not a problem, except arguments to GTK+ callbacks depend on the callback itself. Since we're generating callback functions as simple closures of one type, this file will wrap the generated callbacks in the appropriate callback type. We pass the actual generated pointer to the extra data parameter of the callback.
+*/
+
+// #cgo pkg-config: gtk+-3.0
+// #include <gtk/gtk.h>
+// extern gboolean our_delete_event_callback(GtkWidget *, GdkEvent *, gpointer);
+import "C"
+
+//export our_delete_event_callback
+func our_delete_event_callback(widget *C.GtkWidget, event *C.GdkEvent, what C.gpointer) C.gboolean {
+ f := *(*func() bool)(unsafe.Pointer(what))
+ return togbool(f())
+}
+
+var callbacks = map[string]C.GCallback{
+ "delete-event": C.GCallback(C.our_delete_event_callback),
+}
diff --git a/gtkcalls_unix.go b/gtkcalls_unix.go
index f56e6fc..84e027f 100644
--- a/gtkcalls_unix.go
+++ b/gtkcalls_unix.go
@@ -5,9 +5,7 @@
package main
import (
- "fmt"
"unsafe"
- "reflect"
)
// #cgo pkg-config: gtk+-3.0
@@ -21,10 +19,6 @@ import "C"
type (
gtkWidget C.GtkWidget
-
- // these are needed for signals
- gdkEvent C.GdkEvent
- gpointer C.gpointer
)
func fromgbool(b C.gboolean) bool {
@@ -64,22 +58,16 @@ func gtk_window_new() *gtkWidget {
return (*gtkWidget)(unsafe.Pointer(C.gtk_window_new(0)))
}
-// because *gtkWidget and *C.GtkWidget are not compatible
-func gtkwidget(g *gtkWidget) (*C.GtkWidget) {
- return (*C.GtkWidget)(unsafe.Pointer(g))
+// shorthand
+func gtkwidget(what *gtkWidget) *C.GtkWidget {
+ return (*C.GtkWidget)(unsafe.Pointer(what))
}
-// TODO do we need the argument?
-// TODO fine-tune the function type
-func g_signal_connect(obj *gtkWidget, sig string, callback interface{}) {
- v := reflect.ValueOf(callback)
- if v.Kind() != reflect.Func {
- panic(fmt.Sprintf("UI library internal error: callback %v given to g_signal_connect not a function", v))
- }
- ccallback := C.GCallback(unsafe.Pointer(v.Pointer()))
+func g_signal_connect(obj *gtkWidget, sig string, callback func() bool) {
+ ccallback := callbacks[sig]
csig := C.CString(sig)
defer C.free(unsafe.Pointer(csig))
- C.gSignalConnect(gtkwidget(obj), csig, ccallback, unsafe.Pointer(nil))
+ C.gSignalConnect(gtkwidget(obj), csig, ccallback, unsafe.Pointer(&callback))
}
// TODO ensure this works if called on an individual control
diff --git a/sysdata_unix.go b/sysdata_unix.go
index 3466a8a..9685004 100644
--- a/sysdata_unix.go
+++ b/sysdata_unix.go
@@ -19,16 +19,16 @@ type classData struct {
make func() *gtkWidget
setText func(widget *gtkWidget, text string)
// ...
- signals map[string]func(*sysData) interface{}
+ signals map[string]func(*sysData) func() bool
}
var classTypes = [nctypes]*classData{
c_window: &classData{
make: gtk_window_new,
setText: gtk_window_set_title,
- signals: map[string]func(*sysData) interface{}{
- "delete-event": func(w *sysData) interface{} {
- return func(*gtkWidget, *gdkEvent, gpointer) bool {
+ signals: map[string]func(*sysData) func() bool{
+ "delete-event": func(w *sysData) func() bool {
+ return func() bool {
if w.event != nil {
w.event <- struct{}{}
}