GIR: Expose callbacks in structs as function pointers to Go to allow overwriting vfuncs
Signed-off-by: Felicitas Pojtinger <felicitas@pojtinger.com>
- commit
- c8c33c3bb371be514608fb8313513dda88bcd450
- author
- Felicitas Pojtinger · · 2025-08-26 06:25 UTC
- committer
- Jeroen Wijenbergh · · 2025-10-16 13:39 UTC
- parent
- 18a2e4a
- signature
- unsigned
2 files · +44 -19
M internal/gir/pass/pass.go +22 -13
| @@ -133,21 +133,30 @@ func (p *Pass) writeGo(r types.Repository, gotemp *template.Template, dir string | |||
| 133 | 133 | } | |
| 134 | 134 | } | |
| 135 | 135 | for _, f := range rec.Fields { | |
| 136 | - | _type := f.Translate(ns.Name, p.Types) | |
| 137 | - | if _type == "" { | |
| 138 | - | continue | |
| 139 | - | } | |
| 140 | - | // HACK: Handle the specific case where a gint is converted to an int | |
| 141 | - | // But for structs this needs to be an int32 as purego just gets the pointer to the struct | |
| 142 | - | // Instead of converting each field separately | |
| 143 | - | if f.AnyType.Type != nil && f.AnyType.Type.CType == "gint" { | |
| 144 | - | _type = "int32" | |
| 145 | - | } | |
| 146 | - | ||
| 147 | - | // HACK: in structs the strings should be uintptr as we convert it ourselves | |
| 148 | - | if _type == "string" { | |
| 136 | + | var _type string | |
| 137 | + | ||
| 138 | + | // Check if this field is a callback | |
| 139 | + | if f.Callback != nil { | |
| 140 | + | // Callbacks in structs are function pointers, represented as uintptr | |
| 149 | 141 | _type = "uintptr" | |
| 142 | + | } else { | |
| 143 | + | _type = f.Translate(ns.Name, p.Types) | |
| 144 | + | if _type == "" { | |
| 145 | + | continue | |
| 146 | + | } | |
| 147 | + | // HACK: Handle the specific case where a gint is converted to an int | |
| 148 | + | // But for structs this needs to be an int32 as purego just gets the pointer to the struct | |
| 149 | + | // Instead of converting each field separately | |
| 150 | + | if f.AnyType.Type != nil && f.AnyType.Type.CType == "gint" { | |
| 151 | + | _type = "int32" | |
| 152 | + | } | |
| 153 | + | ||
| 154 | + | // HACK: in structs the strings should be uintptr as we convert it ourselves | |
| 155 | + | if _type == "string" { | |
| 156 | + | _type = "uintptr" | |
| 157 | + | } | |
| 150 | 158 | } | |
| 159 | + | ||
| 151 | 160 | fields = append(fields, types.RecordField{ | |
| 152 | 161 | Name: util.SnakeToCamel(f.Name), | |
| 153 | 162 | Type: _type, | |
| @@ -133,21 +133,30 @@ func (p *Pass) writeGo(r types.Repository, gotemp *template.Template, dir string | |||||
| 133 | } | 133 | } | ||
| 134 | } | 134 | } | ||
| 135 | for _, f := range rec.Fields { | 135 | for _, f := range rec.Fields { | ||
| 136 | - | _type := f.Translate(ns.Name, p.Types) | 136 | + | var _type string |
| 137 | - | if _type == "" { | 137 | + | |
| 138 | - | continue | 138 | + | // Check if this field is a callback |
| 139 | - | } | 139 | + | if f.Callback != nil { |
| 140 | - | // HACK: Handle the specific case where a gint is converted to an int | 140 | + | // Callbacks in structs are function pointers, represented as uintptr |
| 141 | - | // But for structs this needs to be an int32 as purego just gets the pointer to the struct | |||
| 142 | - | // Instead of converting each field separately | |||
| 143 | - | if f.AnyType.Type != nil && f.AnyType.Type.CType == "gint" { | |||
| 144 | - | _type = "int32" | |||
| 145 | - | } | |||
| 146 | - | ||||
| 147 | - | // HACK: in structs the strings should be uintptr as we convert it ourselves | |||
| 148 | - | if _type == "string" { | |||
| 149 | _type = "uintptr" | 141 | _type = "uintptr" | ||
| 142 | + | } else { | |||
| 143 | + | _type = f.Translate(ns.Name, p.Types) | |||
| 144 | + | if _type == "" { | |||
| 145 | + | continue | |||
| 146 | + | } | |||
| 147 | + | // HACK: Handle the specific case where a gint is converted to an int | |||
| 148 | + | // But for structs this needs to be an int32 as purego just gets the pointer to the struct | |||
| 149 | + | // Instead of converting each field separately | |||
| 150 | + | if f.AnyType.Type != nil && f.AnyType.Type.CType == "gint" { | |||
| 151 | + | _type = "int32" | |||
| 152 | + | } | |||
| 153 | + | ||||
| 154 | + | // HACK: in structs the strings should be uintptr as we convert it ourselves | |||
| 155 | + | if _type == "string" { | |||
| 156 | + | _type = "uintptr" | |||
| 157 | + | } | |||
| 150 | } | 158 | } | ||
| 159 | + | ||||
| 151 | fields = append(fields, types.RecordField{ | 160 | fields = append(fields, types.RecordField{ | ||
| 152 | Name: util.SnakeToCamel(f.Name), | 161 | Name: util.SnakeToCamel(f.Name), | ||
| 153 | Type: _type, | 162 | Type: _type, | ||
M templates/go +22 -6
| @@ -3,14 +3,30 @@ package {{.PkgName}} | |||
| 3 | 3 | ||
| 4 | 4 | {{ $NotGObject := ne .PkgName "gobject" }} | |
| 5 | 5 | {{ $NotGLib := ne .PkgName "glib" }} | |
| 6 | + | {{ $HasSignals := false }} | |
| 7 | + | {{range .Classes -}} | |
| 8 | + | {{if .Signals}} | |
| 9 | + | {{ $HasSignals = true }} | |
| 10 | + | {{end}} | |
| 11 | + | {{end}} | |
| 12 | + | {{ $NeedsUnsafe := or .Records $HasSignals }} | |
| 13 | + | {{ $NeedsPurego := or .NeedsInit $HasSignals }} | |
| 14 | + | {{ $AnyImports := or .NeedsInit .Records $HasSignals }} | |
| 6 | 15 | ||
| 7 | - | {{if .NeedsInit}} | |
| 16 | + | {{if $AnyImports}} | |
| 8 | 17 | import ( | |
| 9 | - | {{if .Records}} | |
| 10 | - | "structs" | |
| 11 | - | {{end}} | |
| 12 | - | "github.com/jwijenbergh/purego" | |
| 13 | - | "github.com/jwijenbergh/puregotk/pkg/core" | |
| 18 | + | {{- if $NeedsUnsafe}} | |
| 19 | + | "unsafe" | |
| 20 | + | {{- end}} | |
| 21 | + | {{- if .Records}} | |
| 22 | + | "structs" | |
| 23 | + | {{- end}} | |
| 24 | + | {{- if $NeedsPurego}} | |
| 25 | + | "github.com/jwijenbergh/purego" | |
| 26 | + | {{- end}} | |
| 27 | + | {{- if .NeedsInit}} | |
| 28 | + | "github.com/jwijenbergh/puregotk/pkg/core" | |
| 29 | + | {{- end}} | |
| 14 | 30 | ) | |
| 15 | 31 | {{end}} | |
| 16 | 32 | ||
| @@ -3,14 +3,30 @@ package {{.PkgName}} | |||||
| 3 | 3 | ||||
| 4 | {{ $NotGObject := ne .PkgName "gobject" }} | 4 | {{ $NotGObject := ne .PkgName "gobject" }} | ||
| 5 | {{ $NotGLib := ne .PkgName "glib" }} | 5 | {{ $NotGLib := ne .PkgName "glib" }} | ||
| 6 | + | {{ $HasSignals := false }} | |||
| 7 | + | {{range .Classes -}} | |||
| 8 | + | {{if .Signals}} | |||
| 9 | + | {{ $HasSignals = true }} | |||
| 10 | + | {{end}} | |||
| 11 | + | {{end}} | |||
| 12 | + | {{ $NeedsUnsafe := or .Records $HasSignals }} | |||
| 13 | + | {{ $NeedsPurego := or .NeedsInit $HasSignals }} | |||
| 14 | + | {{ $AnyImports := or .NeedsInit .Records $HasSignals }} | |||
| 6 | 15 | ||||
| 7 | - | {{if .NeedsInit}} | 16 | + | {{if $AnyImports}} |
| 8 | import ( | 17 | import ( | ||
| 9 | - | {{if .Records}} | 18 | + | {{- if $NeedsUnsafe}} |
| 10 | - | "structs" | 19 | + | "unsafe" |
| 11 | - | {{end}} | 20 | + | {{- end}} |
| 12 | - | "github.com/jwijenbergh/purego" | 21 | + | {{- if .Records}} |
| 13 | - | "github.com/jwijenbergh/puregotk/pkg/core" | 22 | + | "structs" |
| 23 | + | {{- end}} | |||
| 24 | + | {{- if $NeedsPurego}} | |||
| 25 | + | "github.com/jwijenbergh/purego" | |||
| 26 | + | {{- end}} | |||
| 27 | + | {{- if .NeedsInit}} | |||
| 28 | + | "github.com/jwijenbergh/puregotk/pkg/core" | |||
| 29 | + | {{- end}} | |||
| 14 | ) | 30 | ) | ||
| 15 | {{end}} | 31 | {{end}} | ||
| 16 | 32 | ||||