Core: Migrate to requiring function pointers for all callback arguments
This lets us correctly track the identity of callbacks. BREAKING CHANGE: All callback-based APIs now require function pointers.
- commit
- c2a1f08c9dfcefe178d91f8c7070caf219ff662b
- author
- Peter Fern · · 2024-01-06 06:48 UTC
- committer
- Jeroen Wijenbergh · · 2024-03-05 11:56 UTC
- parent
- cd00a46
- signature
- unsigned
4 files · +25 -16
M internal/gir/types/template.go +1 -0
| @@ -43,6 +43,7 @@ func (f *funcArgsTemplate) AddAPI(t string, n string, k Kind, ns string) { | |||
| 43 | 43 | switch k { | |
| 44 | 44 | case CallbackType: | |
| 45 | 45 | c = fmt.Sprintf("%sNewCallback(%s)", glibNs, n) | |
| 46 | + | t = "*" + t | |
| 46 | 47 | case ClassesType: | |
| 47 | 48 | if stars == 0 { | |
| 48 | 49 | c = n | |
| @@ -43,6 +43,7 @@ func (f *funcArgsTemplate) AddAPI(t string, n string, k Kind, ns string) { | |||||
| 43 | switch k { | 43 | switch k { | ||
| 44 | case CallbackType: | 44 | case CallbackType: | ||
| 45 | c = fmt.Sprintf("%sNewCallback(%s)", glibNs, n) | 45 | c = fmt.Sprintf("%sNewCallback(%s)", glibNs, n) | ||
| 46 | + | t = "*" + t | |||
| 46 | case ClassesType: | 47 | case ClassesType: | ||
| 47 | if stars == 0 { | 48 | if stars == 0 { | ||
| 48 | c = n | 49 | c = n | ||
M templates/glib +13 -6
| @@ -34,23 +34,30 @@ func SaveCallback(cbPtr uintptr, refPtr uintptr) { | |||
| 34 | 34 | } | |
| 35 | 35 | ||
| 36 | 36 | // UnrefCallbackValue unreferences the provided callback by reflect.value to free a purego slot | |
| 37 | - | func UnrefCallback(fn interface{}) error { | |
| 38 | - | cbPtr := reflect.ValueOf(fn).Pointer() | |
| 37 | + | func UnrefCallback(fnPtr interface{}) error { | |
| 38 | + | val := reflect.ValueOf(fnPtr) | |
| 39 | + | if val.IsNil() { | |
| 40 | + | return fmt.Errorf("function pointer must not be nil") | |
| 41 | + | } | |
| 42 | + | if val.Kind() != reflect.Ptr || val.Elem().Kind() != reflect.Func { | |
| 43 | + | return fmt.Errorf("type must be a function pointer") | |
| 44 | + | } | |
| 45 | + | cbPtr := reflect.ValueOf(fnPtr).Pointer() | |
| 39 | 46 | refPtr, ok := GetCallback(cbPtr) | |
| 40 | 47 | if !ok { | |
| 41 | - | return purego.UnrefCallback(fn) | |
| 48 | + | return purego.UnrefCallbackFnPtr(fnPtr) | |
| 42 | 49 | } | |
| 43 | 50 | defer func() { | |
| 44 | 51 | callbacks.Lock() | |
| 45 | 52 | delete(callbacks.refs, cbPtr) | |
| 46 | 53 | callbacks.Unlock() | |
| 47 | 54 | }() | |
| 48 | - | return purego.UnrefCallbackPtr(refPtr) | |
| 55 | + | return purego.UnrefCallback(refPtr) | |
| 49 | 56 | } | |
| 50 | 57 | ||
| 51 | 58 | // NewCallback is an alias to purego.NewCallback | |
| 52 | - | func NewCallback(fn interface{}) uintptr { | |
| 53 | - | return purego.NewCallback(fn) | |
| 59 | + | func NewCallback(fnPtr interface{}) uintptr { | |
| 60 | + | return purego.NewCallbackFnPtr(fnPtr) | |
| 54 | 61 | } | |
| 55 | 62 | ||
| 56 | 63 | func (e *Error) Error() string { | |
| @@ -34,23 +34,30 @@ func SaveCallback(cbPtr uintptr, refPtr uintptr) { | |||||
| 34 | } | 34 | } | ||
| 35 | 35 | ||||
| 36 | // UnrefCallbackValue unreferences the provided callback by reflect.value to free a purego slot | 36 | // UnrefCallbackValue unreferences the provided callback by reflect.value to free a purego slot | ||
| 37 | - | func UnrefCallback(fn interface{}) error { | 37 | + | func UnrefCallback(fnPtr interface{}) error { |
| 38 | - | cbPtr := reflect.ValueOf(fn).Pointer() | 38 | + | val := reflect.ValueOf(fnPtr) |
| 39 | + | if val.IsNil() { | |||
| 40 | + | return fmt.Errorf("function pointer must not be nil") | |||
| 41 | + | } | |||
| 42 | + | if val.Kind() != reflect.Ptr || val.Elem().Kind() != reflect.Func { | |||
| 43 | + | return fmt.Errorf("type must be a function pointer") | |||
| 44 | + | } | |||
| 45 | + | cbPtr := reflect.ValueOf(fnPtr).Pointer() | |||
| 39 | refPtr, ok := GetCallback(cbPtr) | 46 | refPtr, ok := GetCallback(cbPtr) | ||
| 40 | if !ok { | 47 | if !ok { | ||
| 41 | - | return purego.UnrefCallback(fn) | 48 | + | return purego.UnrefCallbackFnPtr(fnPtr) |
| 42 | } | 49 | } | ||
| 43 | defer func() { | 50 | defer func() { | ||
| 44 | callbacks.Lock() | 51 | callbacks.Lock() | ||
| 45 | delete(callbacks.refs, cbPtr) | 52 | delete(callbacks.refs, cbPtr) | ||
| 46 | callbacks.Unlock() | 53 | callbacks.Unlock() | ||
| 47 | }() | 54 | }() | ||
| 48 | - | return purego.UnrefCallbackPtr(refPtr) | 55 | + | return purego.UnrefCallback(refPtr) |
| 49 | } | 56 | } | ||
| 50 | 57 | ||||
| 51 | // NewCallback is an alias to purego.NewCallback | 58 | // NewCallback is an alias to purego.NewCallback | ||
| 52 | - | func NewCallback(fn interface{}) uintptr { | 59 | + | func NewCallback(fnPtr interface{}) uintptr { |
| 53 | - | return purego.NewCallback(fn) | 60 | + | return purego.NewCallbackFnPtr(fnPtr) |
| 54 | } | 61 | } | ||
| 55 | 62 | ||||
| 56 | func (e *Error) Error() string { | 63 | func (e *Error) Error() string { | ||
M templates/go +6 -5
| @@ -184,20 +184,21 @@ func (c *{{.Name}}) SetGoPointer(ptr uintptr) { | |||
| 184 | 184 | {{range .Signals -}} | |
| 185 | 185 | ||
| 186 | 186 | {{.Doc}} | |
| 187 | - | func (x *{{$outer.Name}}) Connect{{.Name}}(cb func({{$outer.Name}} {{convc .Args.API.Types}}) {{.Ret.Value}}) uint32 { | |
| 188 | - | cbPtr := reflect.ValueOf(cb).Pointer() | |
| 187 | + | func (x *{{$outer.Name}}) Connect{{.Name}}(cb *func({{$outer.Name}} {{convc .Args.API.Types}}) {{.Ret.Value}}) uint32 { | |
| 188 | + | cbPtr := uintptr(unsafe.Pointer(cb)) | |
| 189 | 189 | cbRefPtr, ok := {{if $NotGLib}}glib.{{end}}GetCallback(cbPtr) | |
| 190 | 190 | if !ok { | |
| 191 | 191 | fcb := func(clsPtr uintptr {{convc .Args.Pure.Full}}) {{.Ret.Raw}} { | |
| 192 | 192 | fa := {{$outer.Name}}{} | |
| 193 | 193 | fa.Ptr = clsPtr | |
| 194 | + | cbFn := *cb | |
| 194 | 195 | {{if .Ret.Class}} | |
| 195 | - | {{.Name}}Cls := cb(fa {{convc .Args.Pure.Call}}) | |
| 196 | + | {{.Name}}Cls := cbFn(fa {{convc .Args.Pure.Call}}) | |
| 196 | 197 | return {{.Name}}Cls.Ptr | |
| 197 | 198 | {{else if .Ret.Value}} | |
| 198 | - | return cb(fa {{convc .Args.Pure.Call}}) | |
| 199 | + | return cbFn(fa {{convc .Args.Pure.Call}}) | |
| 199 | 200 | {{else}} | |
| 200 | - | cb(fa {{convc .Args.Pure.Call}}) | |
| 201 | + | cbFn(fa {{convc .Args.Pure.Call}}) | |
| 201 | 202 | {{end}} | |
| 202 | 203 | } | |
| 203 | 204 | cbRefPtr = purego.NewCallback(fcb) | |
| @@ -184,20 +184,21 @@ func (c *{{.Name}}) SetGoPointer(ptr uintptr) { | |||||
| 184 | {{range .Signals -}} | 184 | {{range .Signals -}} | ||
| 185 | 185 | ||||
| 186 | {{.Doc}} | 186 | {{.Doc}} | ||
| 187 | - | func (x *{{$outer.Name}}) Connect{{.Name}}(cb func({{$outer.Name}} {{convc .Args.API.Types}}) {{.Ret.Value}}) uint32 { | 187 | + | func (x *{{$outer.Name}}) Connect{{.Name}}(cb *func({{$outer.Name}} {{convc .Args.API.Types}}) {{.Ret.Value}}) uint32 { |
| 188 | - | cbPtr := reflect.ValueOf(cb).Pointer() | 188 | + | cbPtr := uintptr(unsafe.Pointer(cb)) |
| 189 | cbRefPtr, ok := {{if $NotGLib}}glib.{{end}}GetCallback(cbPtr) | 189 | cbRefPtr, ok := {{if $NotGLib}}glib.{{end}}GetCallback(cbPtr) | ||
| 190 | if !ok { | 190 | if !ok { | ||
| 191 | fcb := func(clsPtr uintptr {{convc .Args.Pure.Full}}) {{.Ret.Raw}} { | 191 | fcb := func(clsPtr uintptr {{convc .Args.Pure.Full}}) {{.Ret.Raw}} { | ||
| 192 | fa := {{$outer.Name}}{} | 192 | fa := {{$outer.Name}}{} | ||
| 193 | fa.Ptr = clsPtr | 193 | fa.Ptr = clsPtr | ||
| 194 | + | cbFn := *cb | |||
| 194 | {{if .Ret.Class}} | 195 | {{if .Ret.Class}} | ||
| 195 | - | {{.Name}}Cls := cb(fa {{convc .Args.Pure.Call}}) | 196 | + | {{.Name}}Cls := cbFn(fa {{convc .Args.Pure.Call}}) |
| 196 | return {{.Name}}Cls.Ptr | 197 | return {{.Name}}Cls.Ptr | ||
| 197 | {{else if .Ret.Value}} | 198 | {{else if .Ret.Value}} | ||
| 198 | - | return cb(fa {{convc .Args.Pure.Call}}) | 199 | + | return cbFn(fa {{convc .Args.Pure.Call}}) |
| 199 | {{else}} | 200 | {{else}} | ||
| 200 | - | cb(fa {{convc .Args.Pure.Call}}) | 201 | + | cbFn(fa {{convc .Args.Pure.Call}}) |
| 201 | {{end}} | 202 | {{end}} | ||
| 202 | } | 203 | } | ||
| 203 | cbRefPtr = purego.NewCallback(fcb) | 204 | cbRefPtr = purego.NewCallback(fcb) | ||
M templates/gobject +5 -5
| @@ -37,17 +37,17 @@ func (o Object) Cast(v Ptr) { | |||
| 37 | 37 | v.SetGoPointer(o.GoPointer()) | |
| 38 | 38 | } | |
| 39 | 39 | ||
| 40 | - | func (o Object) ConnectSignal(signal string, cb func()) uint32 { | |
| 41 | - | return SignalConnect(o.GoPointer(), signal, purego.NewCallback(cb)) | |
| 40 | + | func (o Object) ConnectSignal(signal string, cb *func()) uint32 { | |
| 41 | + | return SignalConnect(o.GoPointer(), signal, glib.NewCallback(cb)) | |
| 42 | 42 | } | |
| 43 | 43 | ||
| 44 | 44 | func (o Object) DisconnectSignal(handler uint32) { | |
| 45 | 45 | SignalHandlerDisconnect(&o, handler) | |
| 46 | 46 | } | |
| 47 | 47 | ||
| 48 | - | // NewCallback is an alias to purego.NewCallback | |
| 49 | - | func NewCallback(fn interface{}) uintptr { | |
| 50 | - | return glib.NewCallback(fn) | |
| 48 | + | // NewCallback is an alias to glib.NewCallback | |
| 49 | + | func NewCallback(fnPtr interface{}) uintptr { | |
| 50 | + | return glib.NewCallback(fnPtr) | |
| 51 | 51 | } | |
| 52 | 52 | ||
| 53 | 53 | // types | |
| @@ -37,17 +37,17 @@ func (o Object) Cast(v Ptr) { | |||||
| 37 | v.SetGoPointer(o.GoPointer()) | 37 | v.SetGoPointer(o.GoPointer()) | ||
| 38 | } | 38 | } | ||
| 39 | 39 | ||||
| 40 | - | func (o Object) ConnectSignal(signal string, cb func()) uint32 { | 40 | + | func (o Object) ConnectSignal(signal string, cb *func()) uint32 { |
| 41 | - | return SignalConnect(o.GoPointer(), signal, purego.NewCallback(cb)) | 41 | + | return SignalConnect(o.GoPointer(), signal, glib.NewCallback(cb)) |
| 42 | } | 42 | } | ||
| 43 | 43 | ||||
| 44 | func (o Object) DisconnectSignal(handler uint32) { | 44 | func (o Object) DisconnectSignal(handler uint32) { | ||
| 45 | SignalHandlerDisconnect(&o, handler) | 45 | SignalHandlerDisconnect(&o, handler) | ||
| 46 | } | 46 | } | ||
| 47 | 47 | ||||
| 48 | - | // NewCallback is an alias to purego.NewCallback | 48 | + | // NewCallback is an alias to glib.NewCallback |
| 49 | - | func NewCallback(fn interface{}) uintptr { | 49 | + | func NewCallback(fnPtr interface{}) uintptr { |
| 50 | - | return glib.NewCallback(fn) | 50 | + | return glib.NewCallback(fnPtr) |
| 51 | } | 51 | } | ||
| 52 | 52 | ||||
| 53 | // types | 53 | // types | ||