detached 53c483e

fix(gen): emit pointer-to-array for fixed-size array params

Upstream purego does not support direct array parameters (reflect.Array
kind) in RegisterFunc. Fixed-size C arrays like 'int fds[2]' are pointer
params at the ABI level. Change the generator to emit *[N]T for non-out
fixed-size array params and pass &param from the API wrapper.

Fixes panic: purego: unsupported kind array
commit
53c483e91bacca21d7e83863cd8b53c0c50b99b4
author
brice · · 2026-03-19 16:57 UTC
parent
2b95a8d
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
10 files · +31 -18
M internal/gir/types/template.go +13 -0
@@ -339,6 +339,19 @@ func (f *funcArgsTemplate) Add(p Parameter, ins string, ns string, kinds KindMap
339339 f.AddAPI(goType, varName, kind, ns, p.Nullable, isOut, ctx, transferFull)
340340 f.AddPure(goType, varName, kind, isOut, p.Nullable, ctx, transferFull)
341341
342+ // Upstream purego does not support direct array parameters (reflect.Array kind).
343+ // Fixed-size C arrays like "int fds[2]" are pointer params at the ABI level.
344+ // For non-out fixed-size array params, change the pure signature to *[N]T and
345+ // pass &param from the API wrapper so purego sees a pointer.
346+ if p.Array != nil && p.Array.FixedSize > 0 && !isOut {
347+ idx := len(f.Pure.Types) - 1
348+ f.Pure.Types[idx] = "*" + f.Pure.Types[idx]
349+ f.Pure.Full[idx] = f.Pure.Names[idx] + " " + f.Pure.Types[idx]
350+ apiIdx := len(f.API.Call) - 1
351+ f.API.Call[apiIdx] = "&" + f.API.Call[apiIdx]
352+ f.API.CallWithRefs[apiIdx] = "&" + f.API.CallWithRefs[apiIdx]
353+ }
354+
342355 // For callback parameters (not out parameters), populate callback metadata
343356 // This enables the template to generate proper closure wrapping
344357 if kind == CallbackType && !isOut {
@@ -339,6 +339,19 @@ func (f *funcArgsTemplate) Add(p Parameter, ins string, ns string, kinds KindMap
339 f.AddAPI(goType, varName, kind, ns, p.Nullable, isOut, ctx, transferFull)339 f.AddAPI(goType, varName, kind, ns, p.Nullable, isOut, ctx, transferFull)
340 f.AddPure(goType, varName, kind, isOut, p.Nullable, ctx, transferFull)340 f.AddPure(goType, varName, kind, isOut, p.Nullable, ctx, transferFull)
341 341
342+ // Upstream purego does not support direct array parameters (reflect.Array kind).
343+ // Fixed-size C arrays like "int fds[2]" are pointer params at the ABI level.
344+ // For non-out fixed-size array params, change the pure signature to *[N]T and
345+ // pass &param from the API wrapper so purego sees a pointer.
346+ if p.Array != nil && p.Array.FixedSize > 0 && !isOut {
347+ idx := len(f.Pure.Types) - 1
348+ f.Pure.Types[idx] = "*" + f.Pure.Types[idx]
349+ f.Pure.Full[idx] = f.Pure.Names[idx] + " " + f.Pure.Types[idx]
350+ apiIdx := len(f.API.Call) - 1
351+ f.API.Call[apiIdx] = "&" + f.API.Call[apiIdx]
352+ f.API.CallWithRefs[apiIdx] = "&" + f.API.CallWithRefs[apiIdx]
353+ }
354+
342 // For callback parameters (not out parameters), populate callback metadata355 // For callback parameters (not out parameters), populate callback metadata
343 // This enables the template to generate proper closure wrapping356 // This enables the template to generate proper closure wrapping
344 if kind == CallbackType && !isOut {357 if kind == CallbackType && !isOut {
M v4/glib/glib-unix.go +2 -2
@@ -207,7 +207,7 @@ func UnixGetPasswdEntry(UserNameVar string) (uintptr, error) {
207207
208208 }
209209
210-var xUnixOpenPipe func([2]int, int, **Error) bool
210+var xUnixOpenPipe func(*[2]int, int, **Error) bool
211211
212212 // Similar to the UNIX pipe() call, but on modern systems like Linux
213213 // uses the pipe2() system call, which atomically creates a pipe with
@@ -231,7 +231,7 @@ var xUnixOpenPipe func([2]int, int, **Error) bool
231231 func UnixOpenPipe(FdsVar [2]int, FlagsVar int) (bool, error) {
232232 var cerr *Error
233233
234- cret := xUnixOpenPipe(FdsVar, FlagsVar, &cerr)
234+ cret := xUnixOpenPipe(&FdsVar, FlagsVar, &cerr)
235235
236236 if cerr == nil {
237237 return cret, nil
@@ -207,7 +207,7 @@ func UnixGetPasswdEntry(UserNameVar string) (uintptr, error) {
207 207
208 }208 }
209 209
210-var xUnixOpenPipe func([2]int, int, **Error) bool210+var xUnixOpenPipe func(*[2]int, int, **Error) bool
211 211
212 // Similar to the UNIX pipe() call, but on modern systems like Linux212 // Similar to the UNIX pipe() call, but on modern systems like Linux
213 // uses the pipe2() system call, which atomically creates a pipe with213 // uses the pipe2() system call, which atomically creates a pipe with
@@ -231,7 +231,7 @@ var xUnixOpenPipe func([2]int, int, **Error) bool
231 func UnixOpenPipe(FdsVar [2]int, FlagsVar int) (bool, error) {231 func UnixOpenPipe(FdsVar [2]int, FlagsVar int) (bool, error) {
232 var cerr *Error232 var cerr *Error
233 233
234- cret := xUnixOpenPipe(FdsVar, FlagsVar, &cerr)234+ cret := xUnixOpenPipe(&FdsVar, FlagsVar, &cerr)
235 235
236 if cerr == nil {236 if cerr == nil {
237 return cret, nil237 return cret, nil
M v4/graphene/graphene-matrix.go +2 -2
@@ -209,13 +209,13 @@ func (x *Matrix) InitFrom2d(XxVar float64, YxVar float64, XyVar float64, YyVar f
209209 return cret
210210 }
211211
212-var xMatrixInitFromFloat func(uintptr, [16]float32) *Matrix
212+var xMatrixInitFromFloat func(uintptr, *[16]float32) *Matrix
213213
214214 // Initializes a #graphene_matrix_t with the given array of floating
215215 // point values.
216216 func (x *Matrix) InitFromFloat(VVar [16]float32) *Matrix {
217217
218- cret := xMatrixInitFromFloat(x.GoPointer(), VVar)
218+ cret := xMatrixInitFromFloat(x.GoPointer(), &VVar)
219219 return cret
220220 }
221221
@@ -209,13 +209,13 @@ func (x *Matrix) InitFrom2d(XxVar float64, YxVar float64, XyVar float64, YyVar f
209 return cret209 return cret
210 }210 }
211 211
212-var xMatrixInitFromFloat func(uintptr, [16]float32) *Matrix212+var xMatrixInitFromFloat func(uintptr, *[16]float32) *Matrix
213 213
214 // Initializes a #graphene_matrix_t with the given array of floating214 // Initializes a #graphene_matrix_t with the given array of floating
215 // point values.215 // point values.
216 func (x *Matrix) InitFromFloat(VVar [16]float32) *Matrix {216 func (x *Matrix) InitFromFloat(VVar [16]float32) *Matrix {
217 217
218- cret := xMatrixInitFromFloat(x.GoPointer(), VVar)218+ cret := xMatrixInitFromFloat(x.GoPointer(), &VVar)
219 return cret219 return cret
220 }220 }
221 221
M v4/graphene/graphene-quad.go +2 -2
@@ -86,12 +86,12 @@ func (x *Quad) Init(P1Var *Point, P2Var *Point, P3Var *Point, P4Var *Point) *Qua
8686 return cret
8787 }
8888
89-var xQuadInitFromPoints func(uintptr, [4]Point) *Quad
89+var xQuadInitFromPoints func(uintptr, *[4]Point) *Quad
9090
9191 // Initializes a #graphene_quad_t using an array of points.
9292 func (x *Quad) InitFromPoints(PointsVar [4]Point) *Quad {
9393
94- cret := xQuadInitFromPoints(x.GoPointer(), PointsVar)
94+ cret := xQuadInitFromPoints(x.GoPointer(), &PointsVar)
9595 return cret
9696 }
9797
@@ -86,12 +86,12 @@ func (x *Quad) Init(P1Var *Point, P2Var *Point, P3Var *Point, P4Var *Point) *Qua
86 return cret86 return cret
87 }87 }
88 88
89-var xQuadInitFromPoints func(uintptr, [4]Point) *Quad89+var xQuadInitFromPoints func(uintptr, *[4]Point) *Quad
90 90
91 // Initializes a #graphene_quad_t using an array of points.91 // Initializes a #graphene_quad_t using an array of points.
92 func (x *Quad) InitFromPoints(PointsVar [4]Point) *Quad {92 func (x *Quad) InitFromPoints(PointsVar [4]Point) *Quad {
93 93
94- cret := xQuadInitFromPoints(x.GoPointer(), PointsVar)94+ cret := xQuadInitFromPoints(x.GoPointer(), &PointsVar)
95 return cret95 return cret
96 }96 }
97 97
M v4/graphene/graphene-triangle.go +2 -2
@@ -180,14 +180,14 @@ func (x *Triangle) GetVertices(AVar *Vec3, BVar *Vec3, CVar *Vec3) {
180180
181181 }
182182
183-var xTriangleInitFromFloat func(uintptr, [3]float32, [3]float32, [3]float32) *Triangle
183+var xTriangleInitFromFloat func(uintptr, *[3]float32, *[3]float32, *[3]float32) *Triangle
184184
185185 // Initializes a #graphene_triangle_t using the three given arrays
186186 // of floating point values, each representing the coordinates of
187187 // a point in 3D space.
188188 func (x *Triangle) InitFromFloat(AVar [3]float32, BVar [3]float32, CVar [3]float32) *Triangle {
189189
190- cret := xTriangleInitFromFloat(x.GoPointer(), AVar, BVar, CVar)
190+ cret := xTriangleInitFromFloat(x.GoPointer(), &AVar, &BVar, &CVar)
191191 return cret
192192 }
193193
@@ -180,14 +180,14 @@ func (x *Triangle) GetVertices(AVar *Vec3, BVar *Vec3, CVar *Vec3) {
180 180
181 }181 }
182 182
183-var xTriangleInitFromFloat func(uintptr, [3]float32, [3]float32, [3]float32) *Triangle183+var xTriangleInitFromFloat func(uintptr, *[3]float32, *[3]float32, *[3]float32) *Triangle
184 184
185 // Initializes a #graphene_triangle_t using the three given arrays185 // Initializes a #graphene_triangle_t using the three given arrays
186 // of floating point values, each representing the coordinates of186 // of floating point values, each representing the coordinates of
187 // a point in 3D space.187 // a point in 3D space.
188 func (x *Triangle) InitFromFloat(AVar [3]float32, BVar [3]float32, CVar [3]float32) *Triangle {188 func (x *Triangle) InitFromFloat(AVar [3]float32, BVar [3]float32, CVar [3]float32) *Triangle {
189 189
190- cret := xTriangleInitFromFloat(x.GoPointer(), AVar, BVar, CVar)190+ cret := xTriangleInitFromFloat(x.GoPointer(), &AVar, &BVar, &CVar)
191 return cret191 return cret
192 }192 }
193 193
M v4/graphene/graphene-vec2.go +2 -2
@@ -120,12 +120,12 @@ func (x *Vec2) Init(XVar float32, YVar float32) *Vec2 {
120120 return cret
121121 }
122122
123-var xVec2InitFromFloat func(uintptr, [2]float32) *Vec2
123+var xVec2InitFromFloat func(uintptr, *[2]float32) *Vec2
124124
125125 // Initializes @v with the contents of the given array.
126126 func (x *Vec2) InitFromFloat(SrcVar [2]float32) *Vec2 {
127127
128- cret := xVec2InitFromFloat(x.GoPointer(), SrcVar)
128+ cret := xVec2InitFromFloat(x.GoPointer(), &SrcVar)
129129 return cret
130130 }
131131
@@ -120,12 +120,12 @@ func (x *Vec2) Init(XVar float32, YVar float32) *Vec2 {
120 return cret120 return cret
121 }121 }
122 122
123-var xVec2InitFromFloat func(uintptr, [2]float32) *Vec2123+var xVec2InitFromFloat func(uintptr, *[2]float32) *Vec2
124 124
125 // Initializes @v with the contents of the given array.125 // Initializes @v with the contents of the given array.
126 func (x *Vec2) InitFromFloat(SrcVar [2]float32) *Vec2 {126 func (x *Vec2) InitFromFloat(SrcVar [2]float32) *Vec2 {
127 127
128- cret := xVec2InitFromFloat(x.GoPointer(), SrcVar)128+ cret := xVec2InitFromFloat(x.GoPointer(), &SrcVar)
129 return cret129 return cret
130 }130 }
131 131
M v4/graphene/graphene-vec3.go +2 -2
@@ -187,12 +187,12 @@ func (x *Vec3) Init(XVar float32, YVar float32, ZVar float32) *Vec3 {
187187 return cret
188188 }
189189
190-var xVec3InitFromFloat func(uintptr, [3]float32) *Vec3
190+var xVec3InitFromFloat func(uintptr, *[3]float32) *Vec3
191191
192192 // Initializes a #graphene_vec3_t with the values from an array.
193193 func (x *Vec3) InitFromFloat(SrcVar [3]float32) *Vec3 {
194194
195- cret := xVec3InitFromFloat(x.GoPointer(), SrcVar)
195+ cret := xVec3InitFromFloat(x.GoPointer(), &SrcVar)
196196 return cret
197197 }
198198
@@ -187,12 +187,12 @@ func (x *Vec3) Init(XVar float32, YVar float32, ZVar float32) *Vec3 {
187 return cret187 return cret
188 }188 }
189 189
190-var xVec3InitFromFloat func(uintptr, [3]float32) *Vec3190+var xVec3InitFromFloat func(uintptr, *[3]float32) *Vec3
191 191
192 // Initializes a #graphene_vec3_t with the values from an array.192 // Initializes a #graphene_vec3_t with the values from an array.
193 func (x *Vec3) InitFromFloat(SrcVar [3]float32) *Vec3 {193 func (x *Vec3) InitFromFloat(SrcVar [3]float32) *Vec3 {
194 194
195- cret := xVec3InitFromFloat(x.GoPointer(), SrcVar)195+ cret := xVec3InitFromFloat(x.GoPointer(), &SrcVar)
196 return cret196 return cret
197 }197 }
198 198
M v4/graphene/graphene-vec4.go +2 -2
@@ -157,12 +157,12 @@ func (x *Vec4) Init(XVar float32, YVar float32, ZVar float32, WVar float32) *Vec
157157 return cret
158158 }
159159
160-var xVec4InitFromFloat func(uintptr, [4]float32) *Vec4
160+var xVec4InitFromFloat func(uintptr, *[4]float32) *Vec4
161161
162162 // Initializes a #graphene_vec4_t with the values inside the given array.
163163 func (x *Vec4) InitFromFloat(SrcVar [4]float32) *Vec4 {
164164
165- cret := xVec4InitFromFloat(x.GoPointer(), SrcVar)
165+ cret := xVec4InitFromFloat(x.GoPointer(), &SrcVar)
166166 return cret
167167 }
168168
@@ -157,12 +157,12 @@ func (x *Vec4) Init(XVar float32, YVar float32, ZVar float32, WVar float32) *Vec
157 return cret157 return cret
158 }158 }
159 159
160-var xVec4InitFromFloat func(uintptr, [4]float32) *Vec4160+var xVec4InitFromFloat func(uintptr, *[4]float32) *Vec4
161 161
162 // Initializes a #graphene_vec4_t with the values inside the given array.162 // Initializes a #graphene_vec4_t with the values inside the given array.
163 func (x *Vec4) InitFromFloat(SrcVar [4]float32) *Vec4 {163 func (x *Vec4) InitFromFloat(SrcVar [4]float32) *Vec4 {
164 164
165- cret := xVec4InitFromFloat(x.GoPointer(), SrcVar)165+ cret := xVec4InitFromFloat(x.GoPointer(), &SrcVar)
166 return cret166 return cret
167 }167 }
168 168
M v4/gsk/gskrendernodeimpl.go +2 -2
@@ -188,7 +188,7 @@ func BorderNodeNewFromInternalPtr(ptr uintptr) *BorderNode {
188188 return cls
189189 }
190190
191-var xNewBorderNode func(*RoundedRect, [4]float32, [4]gdk.RGBA) uintptr
191+var xNewBorderNode func(*RoundedRect, *[4]float32, *[4]gdk.RGBA) uintptr
192192
193193 // Creates a `GskRenderNode` that will stroke a border rectangle inside the
194194 // given @outline.
@@ -197,7 +197,7 @@ var xNewBorderNode func(*RoundedRect, [4]float32, [4]gdk.RGBA) uintptr
197197 func NewBorderNode(OutlineVar *RoundedRect, BorderWidthVar [4]float32, BorderColorVar [4]gdk.RGBA) *BorderNode {
198198 var cls *BorderNode
199199
200- cret := xNewBorderNode(OutlineVar, BorderWidthVar, BorderColorVar)
200+ cret := xNewBorderNode(OutlineVar, &BorderWidthVar, &BorderColorVar)
201201
202202 if cret == 0 {
203203 return nil
@@ -188,7 +188,7 @@ func BorderNodeNewFromInternalPtr(ptr uintptr) *BorderNode {
188 return cls188 return cls
189 }189 }
190 190
191-var xNewBorderNode func(*RoundedRect, [4]float32, [4]gdk.RGBA) uintptr191+var xNewBorderNode func(*RoundedRect, *[4]float32, *[4]gdk.RGBA) uintptr
192 192
193 // Creates a `GskRenderNode` that will stroke a border rectangle inside the193 // Creates a `GskRenderNode` that will stroke a border rectangle inside the
194 // given @outline.194 // given @outline.
@@ -197,7 +197,7 @@ var xNewBorderNode func(*RoundedRect, [4]float32, [4]gdk.RGBA) uintptr
197 func NewBorderNode(OutlineVar *RoundedRect, BorderWidthVar [4]float32, BorderColorVar [4]gdk.RGBA) *BorderNode {197 func NewBorderNode(OutlineVar *RoundedRect, BorderWidthVar [4]float32, BorderColorVar [4]gdk.RGBA) *BorderNode {
198 var cls *BorderNode198 var cls *BorderNode
199 199
200- cret := xNewBorderNode(OutlineVar, BorderWidthVar, BorderColorVar)200+ cret := xNewBorderNode(OutlineVar, &BorderWidthVar, &BorderColorVar)
201 201
202 if cret == 0 {202 if cret == 0 {
203 return nil203 return nil
M v4/gtk/gtksnapshot.go +2 -2
@@ -68,14 +68,14 @@ func NewSnapshot() *Snapshot {
6868 return cls
6969 }
7070
71-var xSnapshotAppendBorder func(uintptr, *gsk.RoundedRect, [4]float32, [4]gdk.RGBA)
71+var xSnapshotAppendBorder func(uintptr, *gsk.RoundedRect, *[4]float32, *[4]gdk.RGBA)
7272
7373 // Appends a stroked border rectangle inside the given @outline.
7474 //
7575 // The four sides of the border can have different widths and colors.
7676 func (x *Snapshot) AppendBorder(OutlineVar *gsk.RoundedRect, BorderWidthVar [4]float32, BorderColorVar [4]gdk.RGBA) {
7777
78- xSnapshotAppendBorder(x.GoPointer(), OutlineVar, BorderWidthVar, BorderColorVar)
78+ xSnapshotAppendBorder(x.GoPointer(), OutlineVar, &BorderWidthVar, &BorderColorVar)
7979
8080 }
8181
@@ -68,14 +68,14 @@ func NewSnapshot() *Snapshot {
68 return cls68 return cls
69 }69 }
70 70
71-var xSnapshotAppendBorder func(uintptr, *gsk.RoundedRect, [4]float32, [4]gdk.RGBA)71+var xSnapshotAppendBorder func(uintptr, *gsk.RoundedRect, *[4]float32, *[4]gdk.RGBA)
72 72
73 // Appends a stroked border rectangle inside the given @outline.73 // Appends a stroked border rectangle inside the given @outline.
74 //74 //
75 // The four sides of the border can have different widths and colors.75 // The four sides of the border can have different widths and colors.
76 func (x *Snapshot) AppendBorder(OutlineVar *gsk.RoundedRect, BorderWidthVar [4]float32, BorderColorVar [4]gdk.RGBA) {76 func (x *Snapshot) AppendBorder(OutlineVar *gsk.RoundedRect, BorderWidthVar [4]float32, BorderColorVar [4]gdk.RGBA) {
77 77
78- xSnapshotAppendBorder(x.GoPointer(), OutlineVar, BorderWidthVar, BorderColorVar)78+ xSnapshotAppendBorder(x.GoPointer(), OutlineVar, &BorderWidthVar, &BorderColorVar)
79 79
80 }80 }
81 81

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close