예제 #1
0
파일: signal.go 프로젝트: reusee/gtk-go
func (self *GObjectObject) Connect(signal string, fun func()) {
	cgo_signal := C.CString(signal)
	defer C.free(unsafe.Pointer(cgo_signal))

	callback := &Callback{uintptr(unsafe.Pointer(&fun)), &fun}
	_callbacks[callback.id] = callback

	C._signal_connect(self.GetGObject(),
		cgo_signal, unsafe.Pointer(callback))
}
예제 #2
0
파일: object.go 프로젝트: seokheonbae/glib
func (o *Object) connect(noi bool, sid SignalId, detail Quark, cb_func,
	param0 interface{}) {
	cb := reflect.ValueOf(cb_func)
	if cb.Kind() != reflect.Func {
		panic("cb_func isn't a function")
	}
	// Check that function parameters and return value match to signal
	var sq C.GSignalQuery

	C.g_signal_query(C.guint(sid), &sq)
	ft := cb.Type()
	if ft.NumOut() > 1 || ft.NumOut() == 1 && Type(sq.return_type) == TYPE_NONE {
		panic("Number of function return values doesn't match signal spec.")
	}
	poffset := 2
	if param0 == nil {
		// There is no param0
		poffset--
	}
	if noi {
		// There is no instance on which signal was emited as first parameter
		poffset--
	} else if !o.Type().Match(ft.In(poffset - 1)) {
		panic(fmt.Sprintf(
			"Callback #%d param. type %s doesn't match signal source: %s",
			poffset-1, ft.In(poffset-1), o.Type(),
		))
	}
	n_params := int(sq.n_params)
	if ft.NumIn() != n_params+poffset {
		panic(fmt.Sprintf(
			"Number of function parameters #%d isn't equal to signal spec: #%d",
			ft.NumIn(), n_params+poffset,
		))
	}
	if ft.NumOut() != 0 && !Type(sq.return_type).Match(ft.Out(0)) {
		panic("Type of function return value doesn't match signal spec.")
	}
	if n_params > 0 {
		pt := (*[1 << 16]Type)(unsafe.Pointer(sq.param_types))[:int(sq.n_params)]
		for i := 0; i < n_params; i++ {
			if !pt[i].Match(ft.In(i + poffset)) {
				panic(fmt.Sprintf(
					"Callback #%d param. type %s doesn't match signal spec %s",
					i+poffset, ft.In(i+poffset), pt[i],
				))
			}
		}
	}
	// Setup closure and connect it to signal
	var gocl *C.GoClosure
	p0 := reflect.ValueOf(param0)
	// Check type of #0 parameter which is set by Connect method
	switch p0.Kind() {
	case reflect.Invalid:
		gocl = C._object_closure_new(gBoolean(noi), nil)
	case reflect.Ptr:
		if !p0.Type().AssignableTo(ft.In(0)) {
			panic(fmt.Sprintf(
				"Callback #0 parameter type: %s doesn't match signal spec: %s",
				ft.In(0), p0.Type(),
			))
		}
		gocl = C._object_closure_new(gBoolean(noi), C.gpointer(p0.Pointer()))
	default:
		panic("Callback parameter #0 isn't a pointer nor nil")
	}
	gocl.h_id = C._signal_connect(o.g(), C.guint(sid), C.GQuark(detail), gocl)
	oh := obj_handlers[uintptr(o.p)]
	if oh == nil {
		oh = make(map[SigHandlerId]*sigHandler)
		obj_handlers[uintptr(o.p)] = oh
	}
	oh[SigHandlerId(gocl.h_id)] = &sigHandler{cb, p0} // p0 for prevent GC
}