detached d6a13f5

fix(core): make NullableStringToPtr GC-safe with runtime.KeepAlive

commit
d6a13f506333397565ac961430c222029ceaa597
author
bnema · · 2025-12-18 04:48 UTC
parent
dd4a135
signature
GPG Unverified2B82207D370127A0 The key is unknown
3 files · +75 -11
M internal/core/core.go +7 -3
@@ -228,11 +228,15 @@ func GoString(c uintptr) string {
228228 }
229229
230230 // NullableStringToPtr converts a nullable Go string to a uintptr suitable for C calls.
231-func NullableStringToPtr(s *string) uintptr {
231+// Returns both the pointer and the backing byte slice. The caller MUST call
232+// runtime.KeepAlive(bytes) after the C call completes to prevent GC from collecting
233+// the memory before C has finished reading it.
234+func NullableStringToPtr(s *string) (uintptr, []byte) {
232235 if s == nil {
233- return 0
236+ return 0, nil
234237 }
235- return uintptr(unsafe.Pointer(CString(*s)))
238+ b := append([]byte(*s), 0)
239+ return uintptr(unsafe.Pointer(&b[0])), b
236240 }
237241
238242 // PtrToNullableString converts a nullable char* to a Go *string (nil when NULL).
@@ -228,11 +228,15 @@ func GoString(c uintptr) string {
228 }228 }
229 229
230 // NullableStringToPtr converts a nullable Go string to a uintptr suitable for C calls.230 // NullableStringToPtr converts a nullable Go string to a uintptr suitable for C calls.
231-func NullableStringToPtr(s *string) uintptr {231+// Returns both the pointer and the backing byte slice. The caller MUST call
232+// runtime.KeepAlive(bytes) after the C call completes to prevent GC from collecting
233+// the memory before C has finished reading it.
234+func NullableStringToPtr(s *string) (uintptr, []byte) {
232 if s == nil {235 if s == nil {
233- return 0236+ return 0, nil
234 }237 }
235- return uintptr(unsafe.Pointer(CString(*s)))238+ b := append([]byte(*s), 0)
239+ return uintptr(unsafe.Pointer(&b[0])), b
236 }240 }
237 241
238 // PtrToNullableString converts a nullable char* to a Go *string (nil when NULL).242 // PtrToNullableString converts a nullable char* to a Go *string (nil when NULL).
M internal/gir/types/template.go +17 -2
@@ -38,6 +38,14 @@ type CallbackParam struct {
3838 Nullable bool
3939 }
4040
41+// NullableStringParam holds metadata for nullable string parameters that need
42+// runtime.KeepAlive to prevent GC from collecting the backing memory before
43+// the C function returns.
44+type NullableStringParam struct {
45+ // Name is the parameter name (e.g., "DataDirectoryVar")
46+ Name string
47+}
48+
4149 type funcArgsTemplate struct {
4250 // Pure are the arguments as passed directly to PureGo
4351 // The pure Call is a special case that contains the arguments for a callback call
@@ -49,6 +57,9 @@ type funcArgsTemplate struct {
4957 // Callbacks tracks callback parameters for proper closure generation
5058 Callbacks []CallbackParam
5159
60+ // NullableStrings tracks nullable string parameters that need runtime.KeepAlive
61+ NullableStrings []NullableStringParam
62+
5263 // UsesNullableHelper indicates nullable string handling that needs core import.
5364 UsesNullableHelper bool
5465 }
@@ -153,11 +164,14 @@ func (f *funcArgsTemplate) AddAPI(t string, n string, k Kind, ns string, nullabl
153164 } else {
154165 // Nullable strings differ based on direction. For Go->C we need a *string API type
155166 // and pass a pointer (or nil) to C. For C->Go we keep the string as-is.
167+ // We track these parameters for runtime.KeepAlive to prevent GC issues.
156168 if ctx == ArgsFromGoToC && nullable && isStringType(t) {
157169 f.UsesNullableHelper = true
158170 t = "*string"
159- c = fmt.Sprintf("core.NullableStringToPtr(%s)", n)
171+ c = fmt.Sprintf("%sPtr", n)
160172 cRef = c
173+ // Track this parameter for keepalive generation
174+ f.NullableStrings = append(f.NullableStrings, NullableStringParam{Name: n})
161175 }
162176
163177 switch k {
@@ -227,7 +241,8 @@ func (f *funcArgsTemplate) AddPure(t string, n string, k Kind, isOut bool, nulla
227241 if ctx == ArgsFromGoToC && nullable && isStringType(t) {
228242 f.UsesNullableHelper = true
229243 t = "uintptr"
230- c = fmt.Sprintf("core.NullableStringToPtr(%s)", strings.TrimSuffix(n, "p"))
244+ // Use the pointer variable that will be set up by the template
245+ c = fmt.Sprintf("%sPtr", strings.TrimSuffix(n, "p"))
231246 }
232247
233248 switch k {
@@ -38,6 +38,14 @@ type CallbackParam struct {
38 Nullable bool38 Nullable bool
39 }39 }
40 40
41+// NullableStringParam holds metadata for nullable string parameters that need
42+// runtime.KeepAlive to prevent GC from collecting the backing memory before
43+// the C function returns.
44+type NullableStringParam struct {
45+ // Name is the parameter name (e.g., "DataDirectoryVar")
46+ Name string
47+}
48+
41 type funcArgsTemplate struct {49 type funcArgsTemplate struct {
42 // Pure are the arguments as passed directly to PureGo50 // Pure are the arguments as passed directly to PureGo
43 // The pure Call is a special case that contains the arguments for a callback call51 // The pure Call is a special case that contains the arguments for a callback call
@@ -49,6 +57,9 @@ type funcArgsTemplate struct {
49 // Callbacks tracks callback parameters for proper closure generation57 // Callbacks tracks callback parameters for proper closure generation
50 Callbacks []CallbackParam58 Callbacks []CallbackParam
51 59
60+ // NullableStrings tracks nullable string parameters that need runtime.KeepAlive
61+ NullableStrings []NullableStringParam
62+
52 // UsesNullableHelper indicates nullable string handling that needs core import.63 // UsesNullableHelper indicates nullable string handling that needs core import.
53 UsesNullableHelper bool64 UsesNullableHelper bool
54 }65 }
@@ -153,11 +164,14 @@ func (f *funcArgsTemplate) AddAPI(t string, n string, k Kind, ns string, nullabl
153 } else {164 } else {
154 // Nullable strings differ based on direction. For Go->C we need a *string API type165 // Nullable strings differ based on direction. For Go->C we need a *string API type
155 // and pass a pointer (or nil) to C. For C->Go we keep the string as-is.166 // and pass a pointer (or nil) to C. For C->Go we keep the string as-is.
167+ // We track these parameters for runtime.KeepAlive to prevent GC issues.
156 if ctx == ArgsFromGoToC && nullable && isStringType(t) {168 if ctx == ArgsFromGoToC && nullable && isStringType(t) {
157 f.UsesNullableHelper = true169 f.UsesNullableHelper = true
158 t = "*string"170 t = "*string"
159- c = fmt.Sprintf("core.NullableStringToPtr(%s)", n)171+ c = fmt.Sprintf("%sPtr", n)
160 cRef = c172 cRef = c
173+ // Track this parameter for keepalive generation
174+ f.NullableStrings = append(f.NullableStrings, NullableStringParam{Name: n})
161 }175 }
162 176
163 switch k {177 switch k {
@@ -227,7 +241,8 @@ func (f *funcArgsTemplate) AddPure(t string, n string, k Kind, isOut bool, nulla
227 if ctx == ArgsFromGoToC && nullable && isStringType(t) {241 if ctx == ArgsFromGoToC && nullable && isStringType(t) {
228 f.UsesNullableHelper = true242 f.UsesNullableHelper = true
229 t = "uintptr"243 t = "uintptr"
230- c = fmt.Sprintf("core.NullableStringToPtr(%s)", strings.TrimSuffix(n, "p"))244+ // Use the pointer variable that will be set up by the template
245+ c = fmt.Sprintf("%sPtr", strings.TrimSuffix(n, "p"))
231 }246 }
232 247
233 switch k {248 switch k {
M templates/go +51 -6
@@ -29,6 +29,9 @@ import (
2929 {{- if $HasDetailedSignals}}
3030 "fmt"
3131 {{- end}}
32+{{- if $NeedsCore}}
33+ "runtime"
34+{{- end}}
3235 {{- if .Records}}
3336 "structs"
3437 {{- end}}
@@ -77,7 +80,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
7780 {{.Doc}}
7881 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
7982 {{.Ret.Preamble $NotGLib}}
80- {{- /* Generate closure wrappers for callback parameters */}}
8183 {{range .Args.Callbacks}}
8284 var {{.Name}}Ref uintptr
8385 if {{.Name}} != nil {
@@ -94,7 +96,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
9496 }
9597 }
9698 {{end}}
99+ {{range .Args.NullableStrings}}
100+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
101+ {{end}}
97102 {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
103+ {{range .Args.NullableStrings}}
104+ runtime.KeepAlive({{.Name}}Bytes)
105+ {{end}}
98106 {{.Ret.Fmt $NotGObject}}
99107 }
100108 {{end}}
@@ -106,7 +114,6 @@ var x{{$outer.Name}}{{.Name}} func(uintptr {{convc .Args.Pure.Types}}) {{.Ret.Ra
106114 {{.Doc}}
107115 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
108116 {{.Ret.Preamble $NotGLib}}
109- {{- /* Generate closure wrappers for callback parameters */}}
110117 {{range .Args.Callbacks}}
111118 var {{.Name}}Ref uintptr
112119 if {{.Name}} != nil {
@@ -123,7 +130,13 @@ func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
123130 }
124131 }
125132 {{end}}
133+ {{range .Args.NullableStrings}}
134+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
135+ {{end}}
126136 {{if .Ret.Value}}cret :={{end}}x{{$outer.Name}}{{.Name}}(x.GoPointer() {{convcd .Args.API.CallWithRefs}})
137+ {{range .Args.NullableStrings}}
138+ runtime.KeepAlive({{.Name}}Bytes)
139+ {{end}}
127140 {{.Ret.Fmt $NotGObject}}
128141 }
129142 {{end}}
@@ -204,7 +217,13 @@ func (x *{{.Name}}Base) SetGoPointer(ptr uintptr) {
204217 {{.Doc}}
205218 func (x *{{$outer.Name}}Base) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
206219 {{.Ret.Preamble $NotGLib}}
220+ {{range .Args.NullableStrings}}
221+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
222+ {{end}}
207223 {{if .Ret.Value}}cret := {{end}}{{.Namespace}}X{{.FullName}}(x.GoPointer() {{convcd .Args.API.Call}})
224+ {{range .Args.NullableStrings}}
225+ runtime.KeepAlive({{.Name}}Bytes)
226+ {{end}}
208227 {{.Ret.Fmt $NotGObject}}
209228 }
210229 {{end}}
@@ -284,7 +303,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
284303 {{.Doc}}
285304 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
286305 {{.Ret.Preamble $NotGLib}}
287- {{- /* Generate closure wrappers for callback parameters */}}
288306 {{range .Args.Callbacks}}
289307 var {{.Name}}Ref uintptr
290308 if {{.Name}} != nil {
@@ -301,7 +319,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
301319 }
302320 }
303321 {{end}}
322+ {{range .Args.NullableStrings}}
323+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
324+ {{end}}
304325 {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
326+ {{range .Args.NullableStrings}}
327+ runtime.KeepAlive({{.Name}}Bytes)
328+ {{end}}
305329 {{.Ret.Fmt $NotGObject}}
306330 }
307331 {{end}}
@@ -336,7 +360,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
336360 {{.Doc}}
337361 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
338362 {{.Ret.Preamble $NotGLib}}
339- {{- /* Generate closure wrappers for callback parameters */}}
340363 {{range .Args.Callbacks}}
341364 var {{.Name}}Ref uintptr
342365 if {{.Name}} != nil {
@@ -353,7 +376,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
353376 }
354377 }
355378 {{end}}
379+ {{range .Args.NullableStrings}}
380+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
381+ {{end}}
356382 {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
383+ {{range .Args.NullableStrings}}
384+ runtime.KeepAlive({{.Name}}Bytes)
385+ {{end}}
357386 {{.Ret.Fmt $NotGObject}}
358387 }
359388 {{end}}
@@ -365,7 +394,6 @@ var x{{$outer.Name}}{{.Name}} func(uintptr {{convc .Args.Pure.Types}}) {{.Ret.Ra
365394 {{.Doc}}
366395 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
367396 {{.Ret.Preamble $NotGLib}}
368- {{- /* Generate closure wrappers for callback parameters */}}
369397 {{range .Args.Callbacks}}
370398 var {{.Name}}Ref uintptr
371399 if {{.Name}} != nil {
@@ -382,7 +410,13 @@ func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
382410 }
383411 }
384412 {{end}}
413+ {{range .Args.NullableStrings}}
414+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
415+ {{end}}
385416 {{if .Ret.Value}}cret :={{end}}x{{$outer.Name}}{{.Name}}(x.GoPointer() {{convcd .Args.API.CallWithRefs}})
417+ {{range .Args.NullableStrings}}
418+ runtime.KeepAlive({{.Name}}Bytes)
419+ {{end}}
386420 {{.Ret.Fmt $NotGObject}}
387421 }
388422 {{end}}
@@ -481,7 +515,13 @@ func (x *{{$outer.Name}}) Connect{{.Name}}WithDetail(detail string, cb *func({{$
481515 {{.Doc}}
482516 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
483517 {{.Ret.Preamble $NotGLib}}
518+ {{range .Args.NullableStrings}}
519+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
520+ {{end}}
484521 {{if .Ret.Value}}cret := {{end}} {{.Namespace}}X{{.FullName}}(x.GoPointer() {{convcd .Args.API.Call}})
522+ {{range .Args.NullableStrings}}
523+ runtime.KeepAlive({{.Name}}Bytes)
524+ {{end}}
485525 {{.Ret.Fmt $NotGObject}}
486526 }
487527 {{end}}
@@ -493,7 +533,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
493533 {{.Doc}}
494534 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
495535 {{.Ret.Preamble $NotGLib}}
496- {{- /* Generate closure wrappers for callback parameters */}}
497536 {{range .Args.Callbacks}}
498537 var {{.Name}}Ref uintptr
499538 if {{.Name}} != nil {
@@ -510,7 +549,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
510549 }
511550 }
512551 {{end}}
552+ {{range .Args.NullableStrings}}
553+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
554+ {{end}}
513555 {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
556+ {{range .Args.NullableStrings}}
557+ runtime.KeepAlive({{.Name}}Bytes)
558+ {{end}}
514559 {{.Ret.Fmt $NotGObject}}
515560 }
516561 {{end}}
@@ -29,6 +29,9 @@ import (
29 {{- if $HasDetailedSignals}}29 {{- if $HasDetailedSignals}}
30 "fmt"30 "fmt"
31 {{- end}}31 {{- end}}
32+{{- if $NeedsCore}}
33+ "runtime"
34+{{- end}}
32 {{- if .Records}}35 {{- if .Records}}
33 "structs"36 "structs"
34 {{- end}}37 {{- end}}
@@ -77,7 +80,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
77 {{.Doc}}80 {{.Doc}}
78 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {81 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
79 {{.Ret.Preamble $NotGLib}}82 {{.Ret.Preamble $NotGLib}}
80- {{- /* Generate closure wrappers for callback parameters */}}
81 {{range .Args.Callbacks}}83 {{range .Args.Callbacks}}
82 var {{.Name}}Ref uintptr84 var {{.Name}}Ref uintptr
83 if {{.Name}} != nil {85 if {{.Name}} != nil {
@@ -94,7 +96,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
94 }96 }
95 }97 }
96 {{end}}98 {{end}}
99+ {{range .Args.NullableStrings}}
100+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
101+ {{end}}
97 {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})102 {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
103+ {{range .Args.NullableStrings}}
104+ runtime.KeepAlive({{.Name}}Bytes)
105+ {{end}}
98 {{.Ret.Fmt $NotGObject}}106 {{.Ret.Fmt $NotGObject}}
99 }107 }
100 {{end}}108 {{end}}
@@ -106,7 +114,6 @@ var x{{$outer.Name}}{{.Name}} func(uintptr {{convc .Args.Pure.Types}}) {{.Ret.Ra
106 {{.Doc}}114 {{.Doc}}
107 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {115 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
108 {{.Ret.Preamble $NotGLib}}116 {{.Ret.Preamble $NotGLib}}
109- {{- /* Generate closure wrappers for callback parameters */}}
110 {{range .Args.Callbacks}}117 {{range .Args.Callbacks}}
111 var {{.Name}}Ref uintptr118 var {{.Name}}Ref uintptr
112 if {{.Name}} != nil {119 if {{.Name}} != nil {
@@ -123,7 +130,13 @@ func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
123 }130 }
124 }131 }
125 {{end}}132 {{end}}
133+ {{range .Args.NullableStrings}}
134+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
135+ {{end}}
126 {{if .Ret.Value}}cret :={{end}}x{{$outer.Name}}{{.Name}}(x.GoPointer() {{convcd .Args.API.CallWithRefs}})136 {{if .Ret.Value}}cret :={{end}}x{{$outer.Name}}{{.Name}}(x.GoPointer() {{convcd .Args.API.CallWithRefs}})
137+ {{range .Args.NullableStrings}}
138+ runtime.KeepAlive({{.Name}}Bytes)
139+ {{end}}
127 {{.Ret.Fmt $NotGObject}}140 {{.Ret.Fmt $NotGObject}}
128 }141 }
129 {{end}}142 {{end}}
@@ -204,7 +217,13 @@ func (x *{{.Name}}Base) SetGoPointer(ptr uintptr) {
204 {{.Doc}}217 {{.Doc}}
205 func (x *{{$outer.Name}}Base) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {218 func (x *{{$outer.Name}}Base) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
206 {{.Ret.Preamble $NotGLib}}219 {{.Ret.Preamble $NotGLib}}
220+ {{range .Args.NullableStrings}}
221+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
222+ {{end}}
207 {{if .Ret.Value}}cret := {{end}}{{.Namespace}}X{{.FullName}}(x.GoPointer() {{convcd .Args.API.Call}})223 {{if .Ret.Value}}cret := {{end}}{{.Namespace}}X{{.FullName}}(x.GoPointer() {{convcd .Args.API.Call}})
224+ {{range .Args.NullableStrings}}
225+ runtime.KeepAlive({{.Name}}Bytes)
226+ {{end}}
208 {{.Ret.Fmt $NotGObject}}227 {{.Ret.Fmt $NotGObject}}
209 }228 }
210 {{end}}229 {{end}}
@@ -284,7 +303,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
284 {{.Doc}}303 {{.Doc}}
285 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {304 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
286 {{.Ret.Preamble $NotGLib}}305 {{.Ret.Preamble $NotGLib}}
287- {{- /* Generate closure wrappers for callback parameters */}}
288 {{range .Args.Callbacks}}306 {{range .Args.Callbacks}}
289 var {{.Name}}Ref uintptr307 var {{.Name}}Ref uintptr
290 if {{.Name}} != nil {308 if {{.Name}} != nil {
@@ -301,7 +319,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
301 }319 }
302 }320 }
303 {{end}}321 {{end}}
322+ {{range .Args.NullableStrings}}
323+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
324+ {{end}}
304 {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})325 {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
326+ {{range .Args.NullableStrings}}
327+ runtime.KeepAlive({{.Name}}Bytes)
328+ {{end}}
305 {{.Ret.Fmt $NotGObject}}329 {{.Ret.Fmt $NotGObject}}
306 }330 }
307 {{end}}331 {{end}}
@@ -336,7 +360,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
336 {{.Doc}}360 {{.Doc}}
337 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {361 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
338 {{.Ret.Preamble $NotGLib}}362 {{.Ret.Preamble $NotGLib}}
339- {{- /* Generate closure wrappers for callback parameters */}}
340 {{range .Args.Callbacks}}363 {{range .Args.Callbacks}}
341 var {{.Name}}Ref uintptr364 var {{.Name}}Ref uintptr
342 if {{.Name}} != nil {365 if {{.Name}} != nil {
@@ -353,7 +376,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
353 }376 }
354 }377 }
355 {{end}}378 {{end}}
379+ {{range .Args.NullableStrings}}
380+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
381+ {{end}}
356 {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})382 {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
383+ {{range .Args.NullableStrings}}
384+ runtime.KeepAlive({{.Name}}Bytes)
385+ {{end}}
357 {{.Ret.Fmt $NotGObject}}386 {{.Ret.Fmt $NotGObject}}
358 }387 }
359 {{end}}388 {{end}}
@@ -365,7 +394,6 @@ var x{{$outer.Name}}{{.Name}} func(uintptr {{convc .Args.Pure.Types}}) {{.Ret.Ra
365 {{.Doc}}394 {{.Doc}}
366 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {395 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
367 {{.Ret.Preamble $NotGLib}}396 {{.Ret.Preamble $NotGLib}}
368- {{- /* Generate closure wrappers for callback parameters */}}
369 {{range .Args.Callbacks}}397 {{range .Args.Callbacks}}
370 var {{.Name}}Ref uintptr398 var {{.Name}}Ref uintptr
371 if {{.Name}} != nil {399 if {{.Name}} != nil {
@@ -382,7 +410,13 @@ func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
382 }410 }
383 }411 }
384 {{end}}412 {{end}}
413+ {{range .Args.NullableStrings}}
414+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
415+ {{end}}
385 {{if .Ret.Value}}cret :={{end}}x{{$outer.Name}}{{.Name}}(x.GoPointer() {{convcd .Args.API.CallWithRefs}})416 {{if .Ret.Value}}cret :={{end}}x{{$outer.Name}}{{.Name}}(x.GoPointer() {{convcd .Args.API.CallWithRefs}})
417+ {{range .Args.NullableStrings}}
418+ runtime.KeepAlive({{.Name}}Bytes)
419+ {{end}}
386 {{.Ret.Fmt $NotGObject}}420 {{.Ret.Fmt $NotGObject}}
387 }421 }
388 {{end}}422 {{end}}
@@ -481,7 +515,13 @@ func (x *{{$outer.Name}}) Connect{{.Name}}WithDetail(detail string, cb *func({{$
481 {{.Doc}}515 {{.Doc}}
482 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {516 func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
483 {{.Ret.Preamble $NotGLib}}517 {{.Ret.Preamble $NotGLib}}
518+ {{range .Args.NullableStrings}}
519+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
520+ {{end}}
484 {{if .Ret.Value}}cret := {{end}} {{.Namespace}}X{{.FullName}}(x.GoPointer() {{convcd .Args.API.Call}})521 {{if .Ret.Value}}cret := {{end}} {{.Namespace}}X{{.FullName}}(x.GoPointer() {{convcd .Args.API.Call}})
522+ {{range .Args.NullableStrings}}
523+ runtime.KeepAlive({{.Name}}Bytes)
524+ {{end}}
485 {{.Ret.Fmt $NotGObject}}525 {{.Ret.Fmt $NotGObject}}
486 }526 }
487 {{end}}527 {{end}}
@@ -493,7 +533,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}}
493 {{.Doc}}533 {{.Doc}}
494 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {534 func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
495 {{.Ret.Preamble $NotGLib}}535 {{.Ret.Preamble $NotGLib}}
496- {{- /* Generate closure wrappers for callback parameters */}}
497 {{range .Args.Callbacks}}536 {{range .Args.Callbacks}}
498 var {{.Name}}Ref uintptr537 var {{.Name}}Ref uintptr
499 if {{.Name}} != nil {538 if {{.Name}} != nil {
@@ -510,7 +549,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} {
510 }549 }
511 }550 }
512 {{end}}551 {{end}}
552+ {{range .Args.NullableStrings}}
553+ {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}})
554+ {{end}}
513 {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})555 {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}})
556+ {{range .Args.NullableStrings}}
557+ runtime.KeepAlive({{.Name}}Bytes)
558+ {{end}}
514 {{.Ret.Fmt $NotGObject}}559 {{.Ret.Fmt $NotGObject}}
515 }560 }
516 {{end}}561 {{end}}

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