Gir: Do a better job at converting array types
Needs dep updates for arrays in Purego
- commit
- 15b4fd9ec240e10643205cb4abfa63f89b6332d4
- author
- Jeroen Wijenbergh · · 2024-12-10 14:38 UTC
- committer
- Jeroen Wijenbergh · · 2025-04-07 12:23 UTC
- parent
- 6bd409b
- signature
- unsigned
7 files · +119 -28
M go.mod +2 -2
| @@ -2,6 +2,6 @@ module github.com/jwijenbergh/puregotk | |||
| 2 | 2 | ||
| 3 | 3 | go 1.20 | |
| 4 | 4 | ||
| 5 | - | require github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c | |
| 5 | + | require github.com/jwijenbergh/purego v0.0.0-20241210143217-aeaa0bfe09e0 | |
| 6 | 6 | ||
| 7 | - | require golang.org/x/sys v0.20.0 // indirect | |
| 7 | + | require golang.org/x/sys v0.28.0 // indirect | |
| @@ -2,6 +2,6 @@ module github.com/jwijenbergh/puregotk | |||||
| 2 | 2 | ||||
| 3 | go 1.20 | 3 | go 1.20 | ||
| 4 | 4 | ||||
| 5 | - | require github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c | 5 | + | require github.com/jwijenbergh/purego v0.0.0-20241210143217-aeaa0bfe09e0 |
| 6 | 6 | ||||
| 7 | - | require golang.org/x/sys v0.20.0 // indirect | 7 | + | require golang.org/x/sys v0.28.0 // indirect |
M go.sum +4 -0
| @@ -1,4 +1,8 @@ | |||
| 1 | 1 | github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c h1:eLy6BBXQIOWVpp+Mu8+6d+oPrT4DRAbN75ruWyTXqrM= | |
| 2 | 2 | github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c/go.mod h1:+ekdIOEa4gfAWPhy5blgdiyIJJez3H7o/9JVV01g0yo= | |
| 3 | + | github.com/jwijenbergh/purego v0.0.0-20241210143217-aeaa0bfe09e0 h1:T+RXKadM+FhXcAtRa5vL03gQkRkeqjasQQo/g0UqF1k= | |
| 4 | + | github.com/jwijenbergh/purego v0.0.0-20241210143217-aeaa0bfe09e0/go.mod h1:+ekdIOEa4gfAWPhy5blgdiyIJJez3H7o/9JVV01g0yo= | |
| 3 | 5 | golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= | |
| 4 | 6 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | |
| 7 | + | golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= | |
| 8 | + | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | |
| @@ -1,4 +1,8 @@ | |||||
| 1 | github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c h1:eLy6BBXQIOWVpp+Mu8+6d+oPrT4DRAbN75ruWyTXqrM= | 1 | github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c h1:eLy6BBXQIOWVpp+Mu8+6d+oPrT4DRAbN75ruWyTXqrM= | ||
| 2 | github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c/go.mod h1:+ekdIOEa4gfAWPhy5blgdiyIJJez3H7o/9JVV01g0yo= | 2 | github.com/jwijenbergh/purego v0.0.0-20240527152122-d7876464a49c/go.mod h1:+ekdIOEa4gfAWPhy5blgdiyIJJez3H7o/9JVV01g0yo= | ||
| 3 | + | github.com/jwijenbergh/purego v0.0.0-20241210143217-aeaa0bfe09e0 h1:T+RXKadM+FhXcAtRa5vL03gQkRkeqjasQQo/g0UqF1k= | |||
| 4 | + | github.com/jwijenbergh/purego v0.0.0-20241210143217-aeaa0bfe09e0/go.mod h1:+ekdIOEa4gfAWPhy5blgdiyIJJez3H7o/9JVV01g0yo= | |||
| 3 | golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= | 5 | golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= | ||
| 4 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | 6 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||
| 7 | + | golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= | |||
| 8 | + | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | |||
M internal/gir/pass/pass.go +1 -1
| @@ -204,7 +204,7 @@ func (p *Pass) writeGo(r types.Repository, gotemp *template.Template, dir string | |||
| 204 | 204 | for _, alias := range ns.Aliases { | |
| 205 | 205 | fn := alias.FilenameSafe() | |
| 206 | 206 | files = append(files, fn) | |
| 207 | - | typeName := alias.Type.Template(ns.Name, p.Types) | |
| 207 | + | typeName := alias.Type.Template(ns.Name, p.Types, false) | |
| 208 | 208 | if typeName == "" { | |
| 209 | 209 | typeName = "uintptr" | |
| 210 | 210 | } | |
| @@ -204,7 +204,7 @@ func (p *Pass) writeGo(r types.Repository, gotemp *template.Template, dir string | |||||
| 204 | for _, alias := range ns.Aliases { | 204 | for _, alias := range ns.Aliases { | ||
| 205 | fn := alias.FilenameSafe() | 205 | fn := alias.FilenameSafe() | ||
| 206 | files = append(files, fn) | 206 | files = append(files, fn) | ||
| 207 | - | typeName := alias.Type.Template(ns.Name, p.Types) | 207 | + | typeName := alias.Type.Template(ns.Name, p.Types, false) |
| 208 | if typeName == "" { | 208 | if typeName == "" { | ||
| 209 | typeName = "uintptr" | 209 | typeName = "uintptr" | ||
| 210 | } | 210 | } | ||
M internal/gir/types/kind.go +9 -1
| @@ -1,6 +1,10 @@ | |||
| 1 | 1 | package types | |
| 2 | 2 | ||
| 3 | - | import "github.com/jwijenbergh/puregotk/internal/gir/util" | |
| 3 | + | import ( | |
| 4 | + | "strings" | |
| 5 | + | ||
| 6 | + | "github.com/jwijenbergh/puregotk/internal/gir/util" | |
| 7 | + | ) | |
| 4 | 8 | ||
| 5 | 9 | type Kind int8 | |
| 6 | 10 | ||
| @@ -11,6 +15,7 @@ const ( | |||
| 11 | 15 | ClassesType | |
| 12 | 16 | InterfacesType | |
| 13 | 17 | RecordsType | |
| 18 | + | SliceType | |
| 14 | 19 | OtherType | |
| 15 | 20 | ) | |
| 16 | 21 | ||
| @@ -34,6 +39,9 @@ func (km KindMap) pair(ns string, name string) KindPair { | |||
| 34 | 39 | } | |
| 35 | 40 | ||
| 36 | 41 | func (km KindMap) Kind(ns string, name string) Kind { | |
| 42 | + | if strings.HasPrefix(name, "[") { | |
| 43 | + | return SliceType | |
| 44 | + | } | |
| 37 | 45 | return km.pair(ns, name).K | |
| 38 | 46 | } | |
| 39 | 47 | ||
| @@ -1,6 +1,10 @@ | |||||
| 1 | package types | 1 | package types | ||
| 2 | 2 | ||||
| 3 | - | import "github.com/jwijenbergh/puregotk/internal/gir/util" | 3 | + | import ( |
| 4 | + | "strings" | |||
| 5 | + | ||||
| 6 | + | "github.com/jwijenbergh/puregotk/internal/gir/util" | |||
| 7 | + | ) | |||
| 4 | 8 | ||||
| 5 | type Kind int8 | 9 | type Kind int8 | ||
| 6 | 10 | ||||
| @@ -11,6 +15,7 @@ const ( | |||||
| 11 | ClassesType | 15 | ClassesType | ||
| 12 | InterfacesType | 16 | InterfacesType | ||
| 13 | RecordsType | 17 | RecordsType | ||
| 18 | + | SliceType | |||
| 14 | OtherType | 19 | OtherType | ||
| 15 | ) | 20 | ) | ||
| 16 | 21 | ||||
| @@ -34,6 +39,9 @@ func (km KindMap) pair(ns string, name string) KindPair { | |||||
| 34 | } | 39 | } | ||
| 35 | 40 | ||||
| 36 | func (km KindMap) Kind(ns string, name string) Kind { | 41 | func (km KindMap) Kind(ns string, name string) Kind { | ||
| 42 | + | if strings.HasPrefix(name, "[") { | |||
| 43 | + | return SliceType | |||
| 44 | + | } | |||
| 37 | return km.pair(ns, name).K | 45 | return km.pair(ns, name).K | ||
| 38 | } | 46 | } | ||
| 39 | 47 | ||||
M internal/gir/types/template.go +4 -4
| @@ -119,15 +119,15 @@ func (f *funcArgsTemplate) Add(p Parameter, ins string, ns string, kinds KindMap | |||
| 119 | 119 | } | |
| 120 | 120 | goType := p.Translate(lns, kinds) | |
| 121 | 121 | kind := kinds.Kind(lns, goType) | |
| 122 | + | ||
| 122 | 123 | stars := strings.Count(goType, "*") | |
| 123 | 124 | goType = util.NormalizeNamespace(ns, goType, true) | |
| 125 | + | ||
| 124 | 126 | if kind != OtherType && kind != UnknownType { | |
| 125 | - | if ins != "" && strings.Count(goType, ".") < 1 { | |
| 126 | - | goType = ins + "." + goType | |
| 127 | - | } | |
| 127 | + | goType = util.AddNamespace(goType, ins) | |
| 128 | 128 | } | |
| 129 | 129 | if stars > 0 { | |
| 130 | - | goType = strings.Repeat("*", stars) + strings.ReplaceAll(goType, "*", "") | |
| 130 | + | goType = util.StarsInFront(strings.ReplaceAll(goType, "*", ""), stars) | |
| 131 | 131 | } | |
| 132 | 132 | ||
| 133 | 133 | // Get a suitable variable name | |
| @@ -119,15 +119,15 @@ func (f *funcArgsTemplate) Add(p Parameter, ins string, ns string, kinds KindMap | |||||
| 119 | } | 119 | } | ||
| 120 | goType := p.Translate(lns, kinds) | 120 | goType := p.Translate(lns, kinds) | ||
| 121 | kind := kinds.Kind(lns, goType) | 121 | kind := kinds.Kind(lns, goType) | ||
| 122 | + | ||||
| 122 | stars := strings.Count(goType, "*") | 123 | stars := strings.Count(goType, "*") | ||
| 123 | goType = util.NormalizeNamespace(ns, goType, true) | 124 | goType = util.NormalizeNamespace(ns, goType, true) | ||
| 125 | + | ||||
| 124 | if kind != OtherType && kind != UnknownType { | 126 | if kind != OtherType && kind != UnknownType { | ||
| 125 | - | if ins != "" && strings.Count(goType, ".") < 1 { | 127 | + | goType = util.AddNamespace(goType, ins) |
| 126 | - | goType = ins + "." + goType | |||
| 127 | - | } | |||
| 128 | } | 128 | } | ||
| 129 | if stars > 0 { | 129 | if stars > 0 { | ||
| 130 | - | goType = strings.Repeat("*", stars) + strings.ReplaceAll(goType, "*", "") | 130 | + | goType = util.StarsInFront(strings.ReplaceAll(goType, "*", ""), stars) |
| 131 | } | 131 | } | ||
| 132 | 132 | ||||
| 133 | // Get a suitable variable name | 133 | // Get a suitable variable name | ||
M internal/gir/types/types.go +68 -20
| @@ -44,15 +44,16 @@ var convList = map[string]string{ | |||
| 44 | 44 | "GType": "types.GType", | |
| 45 | 45 | ||
| 46 | 46 | // these are probably not correct but needed to compile | |
| 47 | - | "long double": "float64", | |
| 48 | - | "va_list": "[]interface{}", | |
| 49 | - | "gpointer": "uintptr", | |
| 50 | - | "GType": "[]interface{}", | |
| 51 | - | "const char*": "string", | |
| 52 | - | "const char**": "[]string", | |
| 53 | - | "char**": "[]string", | |
| 47 | + | "_Value__data__union": "uint64", | |
| 48 | + | "long double": "float64", | |
| 49 | + | "va_list": "[]interface{}", | |
| 50 | + | "gpointer": "uintptr", | |
| 51 | + | "const char*": "string", | |
| 52 | + | "const char**": "[]string", | |
| 53 | + | "char**": "[]string", | |
| 54 | 54 | // not exported | |
| 55 | - | "HarfBuzz.font_t": "uintptr", | |
| 55 | + | "HarfBuzz.feature_t": "uintptr", | |
| 56 | + | "HarfBuzz.font_t": "uintptr", | |
| 56 | 57 | //"GLib.Quark": "byte", | |
| 57 | 58 | //"Allocation": "uintptr", | |
| 58 | 59 | } | |
| @@ -99,14 +100,12 @@ func (a *AnyType) Translate(ns string, kinds KindMap) string { | |||
| 99 | 100 | t := a.Type | |
| 100 | 101 | if t == nil { | |
| 101 | 102 | if a.Array == nil { | |
| 103 | + | // no type information available | |
| 102 | 104 | return "" | |
| 103 | 105 | } | |
| 104 | - | if v, ok := convList[a.Array.CType]; ok { | |
| 105 | - | return v | |
| 106 | - | } | |
| 107 | - | return "uintptr" | |
| 106 | + | return a.Array.Template(ns, kinds) | |
| 108 | 107 | } | |
| 109 | - | return a.Type.Template(ns, kinds) | |
| 108 | + | return a.Type.Template(ns, kinds, false) | |
| 110 | 109 | } | |
| 111 | 110 | ||
| 112 | 111 | type Annotation struct { | |
| @@ -127,6 +126,48 @@ type Array struct { | |||
| 127 | 126 | Type *Type `xml:"http://www.gtk.org/introspection/core/1.0 type"` | |
| 128 | 127 | } | |
| 129 | 128 | ||
| 129 | + | func (a *Array) Size() int { | |
| 130 | + | // there is a Length property | |
| 131 | + | // but it seems that GTK doesn't really use this | |
| 132 | + | // see e.g. gtk_css_provider_load_from_data | |
| 133 | + | //if a.Length != nil { | |
| 134 | + | // return *a.Length | |
| 135 | + | //} | |
| 136 | + | return a.FixedSize | |
| 137 | + | } | |
| 138 | + | ||
| 139 | + | func ReplaceSize(str string, n int) string { | |
| 140 | + | trimmed := strings.TrimPrefix(str, "*") | |
| 141 | + | if trimmed == str { | |
| 142 | + | trimmed = strings.TrimPrefix(str, "[]") | |
| 143 | + | } | |
| 144 | + | return fmt.Sprintf("[%d]%s", n, trimmed) | |
| 145 | + | } | |
| 146 | + | ||
| 147 | + | func (a *Array) Template(ns string, kinds KindMap) string { | |
| 148 | + | // Does the c type exist in our little hacky conversion rule? | |
| 149 | + | if v, ok := convList[a.CType]; ok { | |
| 150 | + | return v | |
| 151 | + | } | |
| 152 | + | // default case of an array is just a pointer | |
| 153 | + | ret := "uintptr" | |
| 154 | + | ||
| 155 | + | if a.Type != nil { | |
| 156 | + | t := a.Type.Template(ns, kinds, true) | |
| 157 | + | if strings.Count(t, "*") > 0 { | |
| 158 | + | return "uintptr" | |
| 159 | + | } | |
| 160 | + | ret = "[]" + t | |
| 161 | + | } | |
| 162 | + | ||
| 163 | + | // Check if there is a fixed size | |
| 164 | + | n := a.Size() | |
| 165 | + | if n > 0 { | |
| 166 | + | return ReplaceSize(ret, n) | |
| 167 | + | } | |
| 168 | + | return ret | |
| 169 | + | } | |
| 170 | + | ||
| 130 | 171 | // IsZeroTerminated returns true if the Array is zero-terminated. It accounts | |
| 131 | 172 | // for edge cases of the structure. | |
| 132 | 173 | func (a Array) IsZeroTerminated() bool { | |
| @@ -217,7 +258,7 @@ func (typ *Type) IsIntrospectable() bool { | |||
| 217 | 258 | return typ.Introspectable == nil || *typ.Introspectable | |
| 218 | 259 | } | |
| 219 | 260 | ||
| 220 | - | func (t *Type) Template(ns string, kinds KindMap) string { | |
| 261 | + | func (t *Type) Template(ns string, kinds KindMap, array bool) string { | |
| 221 | 262 | if v, ok := convList[t.Name]; ok { | |
| 222 | 263 | return v | |
| 223 | 264 | } | |
| @@ -235,6 +276,9 @@ func (t *Type) Template(ns string, kinds KindMap) string { | |||
| 235 | 276 | if count > 0 && kind != CallbackType { | |
| 236 | 277 | _type = strings.Repeat("*", count) + _type | |
| 237 | 278 | } else if kind == RecordsType { | |
| 279 | + | if array { | |
| 280 | + | return _type | |
| 281 | + | } | |
| 238 | 282 | // if it's not a pointer | |
| 239 | 283 | // then purego doesn't support it (struct by value is not supported | |
| 240 | 284 | // so return uintptr | |
| @@ -336,7 +380,7 @@ type Constant struct { | |||
| 336 | 380 | } | |
| 337 | 381 | ||
| 338 | 382 | func (c *Constant) Template(ns string, kinds KindMap) ConstantTemplate { | |
| 339 | - | t := c.Type.Template(ns, kinds) | |
| 383 | + | t := c.Type.Template(ns, kinds, false) | |
| 340 | 384 | v := c.Value | |
| 341 | 385 | ||
| 342 | 386 | switch t { | |
| @@ -692,18 +736,22 @@ func (r *ReturnValue) Template(ns string, ins string, kinds KindMap, throws bool | |||
| 692 | 736 | } | |
| 693 | 737 | kind := kinds.Kind(lns, raw) | |
| 694 | 738 | stars := strings.Count(val, "*") | |
| 695 | - | if kind != OtherType && kind != UnknownType { | |
| 696 | - | if ins != "" && strings.Count(val, ".") < 1 { | |
| 697 | - | val = ins + "." + val | |
| 698 | - | } | |
| 739 | + | ||
| 740 | + | if kind != OtherType && kind != UnknownType && kind != SliceType { | |
| 741 | + | val = util.AddNamespace(val, ins) | |
| 699 | 742 | } | |
| 700 | 743 | if stars > 0 { | |
| 701 | - | val = strings.Repeat("*", stars) + strings.ReplaceAll(val, "*", "") | |
| 744 | + | val = util.StarsInFront(strings.ReplaceAll(val, "*", ""), stars) | |
| 702 | 745 | } | |
| 703 | 746 | switch kind { | |
| 704 | 747 | case ClassesType: | |
| 705 | 748 | raw = "uintptr" | |
| 706 | 749 | class = true | |
| 750 | + | // TODO: why does this happen? | |
| 751 | + | if strings.HasPrefix(val, "[]") { | |
| 752 | + | class = false | |
| 753 | + | val = "uintptr" | |
| 754 | + | } | |
| 707 | 755 | case InterfacesType: | |
| 708 | 756 | raw = "uintptr" | |
| 709 | 757 | val += "Base" | |
| @@ -44,15 +44,16 @@ var convList = map[string]string{ | |||||
| 44 | "GType": "types.GType", | 44 | "GType": "types.GType", | ||
| 45 | 45 | ||||
| 46 | // these are probably not correct but needed to compile | 46 | // these are probably not correct but needed to compile | ||
| 47 | - | "long double": "float64", | 47 | + | "_Value__data__union": "uint64", |
| 48 | - | "va_list": "[]interface{}", | 48 | + | "long double": "float64", |
| 49 | - | "gpointer": "uintptr", | 49 | + | "va_list": "[]interface{}", |
| 50 | - | "GType": "[]interface{}", | 50 | + | "gpointer": "uintptr", |
| 51 | - | "const char*": "string", | 51 | + | "const char*": "string", |
| 52 | - | "const char**": "[]string", | 52 | + | "const char**": "[]string", |
| 53 | - | "char**": "[]string", | 53 | + | "char**": "[]string", |
| 54 | // not exported | 54 | // not exported | ||
| 55 | - | "HarfBuzz.font_t": "uintptr", | 55 | + | "HarfBuzz.feature_t": "uintptr", |
| 56 | + | "HarfBuzz.font_t": "uintptr", | |||
| 56 | //"GLib.Quark": "byte", | 57 | //"GLib.Quark": "byte", | ||
| 57 | //"Allocation": "uintptr", | 58 | //"Allocation": "uintptr", | ||
| 58 | } | 59 | } | ||
| @@ -99,14 +100,12 @@ func (a *AnyType) Translate(ns string, kinds KindMap) string { | |||||
| 99 | t := a.Type | 100 | t := a.Type | ||
| 100 | if t == nil { | 101 | if t == nil { | ||
| 101 | if a.Array == nil { | 102 | if a.Array == nil { | ||
| 103 | + | // no type information available | |||
| 102 | return "" | 104 | return "" | ||
| 103 | } | 105 | } | ||
| 104 | - | if v, ok := convList[a.Array.CType]; ok { | 106 | + | return a.Array.Template(ns, kinds) |
| 105 | - | return v | |||
| 106 | - | } | |||
| 107 | - | return "uintptr" | |||
| 108 | } | 107 | } | ||
| 109 | - | return a.Type.Template(ns, kinds) | 108 | + | return a.Type.Template(ns, kinds, false) |
| 110 | } | 109 | } | ||
| 111 | 110 | ||||
| 112 | type Annotation struct { | 111 | type Annotation struct { | ||
| @@ -127,6 +126,48 @@ type Array struct { | |||||
| 127 | Type *Type `xml:"http://www.gtk.org/introspection/core/1.0 type"` | 126 | Type *Type `xml:"http://www.gtk.org/introspection/core/1.0 type"` | ||
| 128 | } | 127 | } | ||
| 129 | 128 | ||||
| 129 | + | func (a *Array) Size() int { | |||
| 130 | + | // there is a Length property | |||
| 131 | + | // but it seems that GTK doesn't really use this | |||
| 132 | + | // see e.g. gtk_css_provider_load_from_data | |||
| 133 | + | //if a.Length != nil { | |||
| 134 | + | // return *a.Length | |||
| 135 | + | //} | |||
| 136 | + | return a.FixedSize | |||
| 137 | + | } | |||
| 138 | + | ||||
| 139 | + | func ReplaceSize(str string, n int) string { | |||
| 140 | + | trimmed := strings.TrimPrefix(str, "*") | |||
| 141 | + | if trimmed == str { | |||
| 142 | + | trimmed = strings.TrimPrefix(str, "[]") | |||
| 143 | + | } | |||
| 144 | + | return fmt.Sprintf("[%d]%s", n, trimmed) | |||
| 145 | + | } | |||
| 146 | + | ||||
| 147 | + | func (a *Array) Template(ns string, kinds KindMap) string { | |||
| 148 | + | // Does the c type exist in our little hacky conversion rule? | |||
| 149 | + | if v, ok := convList[a.CType]; ok { | |||
| 150 | + | return v | |||
| 151 | + | } | |||
| 152 | + | // default case of an array is just a pointer | |||
| 153 | + | ret := "uintptr" | |||
| 154 | + | ||||
| 155 | + | if a.Type != nil { | |||
| 156 | + | t := a.Type.Template(ns, kinds, true) | |||
| 157 | + | if strings.Count(t, "*") > 0 { | |||
| 158 | + | return "uintptr" | |||
| 159 | + | } | |||
| 160 | + | ret = "[]" + t | |||
| 161 | + | } | |||
| 162 | + | ||||
| 163 | + | // Check if there is a fixed size | |||
| 164 | + | n := a.Size() | |||
| 165 | + | if n > 0 { | |||
| 166 | + | return ReplaceSize(ret, n) | |||
| 167 | + | } | |||
| 168 | + | return ret | |||
| 169 | + | } | |||
| 170 | + | ||||
| 130 | // IsZeroTerminated returns true if the Array is zero-terminated. It accounts | 171 | // IsZeroTerminated returns true if the Array is zero-terminated. It accounts | ||
| 131 | // for edge cases of the structure. | 172 | // for edge cases of the structure. | ||
| 132 | func (a Array) IsZeroTerminated() bool { | 173 | func (a Array) IsZeroTerminated() bool { | ||
| @@ -217,7 +258,7 @@ func (typ *Type) IsIntrospectable() bool { | |||||
| 217 | return typ.Introspectable == nil || *typ.Introspectable | 258 | return typ.Introspectable == nil || *typ.Introspectable | ||
| 218 | } | 259 | } | ||
| 219 | 260 | ||||
| 220 | - | func (t *Type) Template(ns string, kinds KindMap) string { | 261 | + | func (t *Type) Template(ns string, kinds KindMap, array bool) string { |
| 221 | if v, ok := convList[t.Name]; ok { | 262 | if v, ok := convList[t.Name]; ok { | ||
| 222 | return v | 263 | return v | ||
| 223 | } | 264 | } | ||
| @@ -235,6 +276,9 @@ func (t *Type) Template(ns string, kinds KindMap) string { | |||||
| 235 | if count > 0 && kind != CallbackType { | 276 | if count > 0 && kind != CallbackType { | ||
| 236 | _type = strings.Repeat("*", count) + _type | 277 | _type = strings.Repeat("*", count) + _type | ||
| 237 | } else if kind == RecordsType { | 278 | } else if kind == RecordsType { | ||
| 279 | + | if array { | |||
| 280 | + | return _type | |||
| 281 | + | } | |||
| 238 | // if it's not a pointer | 282 | // if it's not a pointer | ||
| 239 | // then purego doesn't support it (struct by value is not supported | 283 | // then purego doesn't support it (struct by value is not supported | ||
| 240 | // so return uintptr | 284 | // so return uintptr | ||
| @@ -336,7 +380,7 @@ type Constant struct { | |||||
| 336 | } | 380 | } | ||
| 337 | 381 | ||||
| 338 | func (c *Constant) Template(ns string, kinds KindMap) ConstantTemplate { | 382 | func (c *Constant) Template(ns string, kinds KindMap) ConstantTemplate { | ||
| 339 | - | t := c.Type.Template(ns, kinds) | 383 | + | t := c.Type.Template(ns, kinds, false) |
| 340 | v := c.Value | 384 | v := c.Value | ||
| 341 | 385 | ||||
| 342 | switch t { | 386 | switch t { | ||
| @@ -692,18 +736,22 @@ func (r *ReturnValue) Template(ns string, ins string, kinds KindMap, throws bool | |||||
| 692 | } | 736 | } | ||
| 693 | kind := kinds.Kind(lns, raw) | 737 | kind := kinds.Kind(lns, raw) | ||
| 694 | stars := strings.Count(val, "*") | 738 | stars := strings.Count(val, "*") | ||
| 695 | - | if kind != OtherType && kind != UnknownType { | 739 | + | |
| 696 | - | if ins != "" && strings.Count(val, ".") < 1 { | 740 | + | if kind != OtherType && kind != UnknownType && kind != SliceType { |
| 697 | - | val = ins + "." + val | 741 | + | val = util.AddNamespace(val, ins) |
| 698 | - | } | |||
| 699 | } | 742 | } | ||
| 700 | if stars > 0 { | 743 | if stars > 0 { | ||
| 701 | - | val = strings.Repeat("*", stars) + strings.ReplaceAll(val, "*", "") | 744 | + | val = util.StarsInFront(strings.ReplaceAll(val, "*", ""), stars) |
| 702 | } | 745 | } | ||
| 703 | switch kind { | 746 | switch kind { | ||
| 704 | case ClassesType: | 747 | case ClassesType: | ||
| 705 | raw = "uintptr" | 748 | raw = "uintptr" | ||
| 706 | class = true | 749 | class = true | ||
| 750 | + | // TODO: why does this happen? | |||
| 751 | + | if strings.HasPrefix(val, "[]") { | |||
| 752 | + | class = false | |||
| 753 | + | val = "uintptr" | |||
| 754 | + | } | |||
| 707 | case InterfacesType: | 755 | case InterfacesType: | ||
| 708 | raw = "uintptr" | 756 | raw = "uintptr" | ||
| 709 | val += "Base" | 757 | val += "Base" | ||
M internal/gir/util/util.go +31 -0
| @@ -19,6 +19,20 @@ func delimToCamel(s string, delim string) string { | |||
| 19 | 19 | return sb.String() | |
| 20 | 20 | } | |
| 21 | 21 | ||
| 22 | + | // StarsInFront adds pointer characters (*, stars) in front of the type | |
| 23 | + | // if there is a slice in front | |
| 24 | + | // we need to add the slice and then afterwards the stars | |
| 25 | + | // e.g. [2]foo becomes [2]*foo with n=1 | |
| 26 | + | func StarsInFront(str string, n int) string { | |
| 27 | + | b := strings.Index(str, "[") | |
| 28 | + | e := strings.Index(str, "]") | |
| 29 | + | stars := strings.Repeat("*", n) | |
| 30 | + | if b == 0 && e != -1 { | |
| 31 | + | return str[b:e+1] + stars + str[e+1:len(str)] | |
| 32 | + | } | |
| 33 | + | return stars + str | |
| 34 | + | } | |
| 35 | + | ||
| 22 | 36 | // SnakeToCamel converts hello_world to HelloWorld | |
| 23 | 37 | func SnakeToCamel(s string) string { | |
| 24 | 38 | return delimToCamel(s, "_") | |
| @@ -53,6 +67,23 @@ func ReplaceExtension(filename string, ext string) string { | |||
| 53 | 67 | return strings.Join(splt, ".") | |
| 54 | 68 | } | |
| 55 | 69 | ||
| 70 | + | func PrefixValue(val, prefix string) string { | |
| 71 | + | // if it's a slice, it has to come first | |
| 72 | + | b := strings.Index(val, "[") | |
| 73 | + | e := strings.Index(val, "]") | |
| 74 | + | if b == 0 && e != -1 { | |
| 75 | + | return val[b:e+1] + prefix + val[e+1:] | |
| 76 | + | } | |
| 77 | + | return prefix + val | |
| 78 | + | } | |
| 79 | + | ||
| 80 | + | func AddNamespace(val, ns string) string { | |
| 81 | + | if ns == "" || strings.Count(val, ".") >= 1 { | |
| 82 | + | return val | |
| 83 | + | } | |
| 84 | + | return PrefixValue(val, ns+".") | |
| 85 | + | } | |
| 86 | + | ||
| 56 | 87 | // NormalizeNamespace converts a type to one that always includes a lowercase namespace | |
| 57 | 88 | // if no namespace is found, it adds `ns`, unless if strip is True then namespaces always equaling `ns` will be removed | |
| 58 | 89 | func NormalizeNamespace(ns string, gotype string, strip bool) string { | |
| @@ -19,6 +19,20 @@ func delimToCamel(s string, delim string) string { | |||||
| 19 | return sb.String() | 19 | return sb.String() | ||
| 20 | } | 20 | } | ||
| 21 | 21 | ||||
| 22 | + | // StarsInFront adds pointer characters (*, stars) in front of the type | |||
| 23 | + | // if there is a slice in front | |||
| 24 | + | // we need to add the slice and then afterwards the stars | |||
| 25 | + | // e.g. [2]foo becomes [2]*foo with n=1 | |||
| 26 | + | func StarsInFront(str string, n int) string { | |||
| 27 | + | b := strings.Index(str, "[") | |||
| 28 | + | e := strings.Index(str, "]") | |||
| 29 | + | stars := strings.Repeat("*", n) | |||
| 30 | + | if b == 0 && e != -1 { | |||
| 31 | + | return str[b:e+1] + stars + str[e+1:len(str)] | |||
| 32 | + | } | |||
| 33 | + | return stars + str | |||
| 34 | + | } | |||
| 35 | + | ||||
| 22 | // SnakeToCamel converts hello_world to HelloWorld | 36 | // SnakeToCamel converts hello_world to HelloWorld | ||
| 23 | func SnakeToCamel(s string) string { | 37 | func SnakeToCamel(s string) string { | ||
| 24 | return delimToCamel(s, "_") | 38 | return delimToCamel(s, "_") | ||
| @@ -53,6 +67,23 @@ func ReplaceExtension(filename string, ext string) string { | |||||
| 53 | return strings.Join(splt, ".") | 67 | return strings.Join(splt, ".") | ||
| 54 | } | 68 | } | ||
| 55 | 69 | ||||
| 70 | + | func PrefixValue(val, prefix string) string { | |||
| 71 | + | // if it's a slice, it has to come first | |||
| 72 | + | b := strings.Index(val, "[") | |||
| 73 | + | e := strings.Index(val, "]") | |||
| 74 | + | if b == 0 && e != -1 { | |||
| 75 | + | return val[b:e+1] + prefix + val[e+1:] | |||
| 76 | + | } | |||
| 77 | + | return prefix + val | |||
| 78 | + | } | |||
| 79 | + | ||||
| 80 | + | func AddNamespace(val, ns string) string { | |||
| 81 | + | if ns == "" || strings.Count(val, ".") >= 1 { | |||
| 82 | + | return val | |||
| 83 | + | } | |||
| 84 | + | return PrefixValue(val, ns+".") | |||
| 85 | + | } | |||
| 86 | + | ||||
| 56 | // NormalizeNamespace converts a type to one that always includes a lowercase namespace | 87 | // NormalizeNamespace converts a type to one that always includes a lowercase namespace | ||
| 57 | // if no namespace is found, it adds `ns`, unless if strip is True then namespaces always equaling `ns` will be removed | 88 | // if no namespace is found, it adds `ns`, unless if strip is True then namespaces always equaling `ns` will be removed | ||
| 58 | func NormalizeNamespace(ns string, gotype string, strip bool) string { | 89 | func NormalizeNamespace(ns string, gotype string, strip bool) string { | ||