fix(core): make NullableStringToPtr GC-safe with runtime.KeepAlive
- commit
- d6a13f506333397565ac961430c222029ceaa597
- author
- bnema · · 2025-12-18 04:48 UTC
- parent
- dd4a135
- signature
- GPG Unverified
2B82207D370127A0The key is unknown
3 files · +75 -11
M internal/core/core.go +7 -3
| @@ -228,11 +228,15 @@ func GoString(c uintptr) string { | |||
| 228 | 228 | } | |
| 229 | 229 | ||
| 230 | 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 | 235 | if s == nil { | |
| 233 | - | return 0 | |
| 236 | + | 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 | 242 | // 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 0 | 236 | + | 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 { | |||
| 38 | 38 | 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 | 49 | type funcArgsTemplate struct { | |
| 42 | 50 | // Pure are the arguments as passed directly to PureGo | |
| 43 | 51 | // The pure Call is a special case that contains the arguments for a callback call | |
| @@ -49,6 +57,9 @@ type funcArgsTemplate struct { | |||
| 49 | 57 | // Callbacks tracks callback parameters for proper closure generation | |
| 50 | 58 | Callbacks []CallbackParam | |
| 51 | 59 | ||
| 60 | + | // NullableStrings tracks nullable string parameters that need runtime.KeepAlive | |
| 61 | + | NullableStrings []NullableStringParam | |
| 62 | + | ||
| 52 | 63 | // UsesNullableHelper indicates nullable string handling that needs core import. | |
| 53 | 64 | UsesNullableHelper bool | |
| 54 | 65 | } | |
| @@ -153,11 +164,14 @@ func (f *funcArgsTemplate) AddAPI(t string, n string, k Kind, ns string, nullabl | |||
| 153 | 164 | } else { | |
| 154 | 165 | // Nullable strings differ based on direction. For Go->C we need a *string API type | |
| 155 | 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 | 168 | if ctx == ArgsFromGoToC && nullable && isStringType(t) { | |
| 157 | 169 | f.UsesNullableHelper = true | |
| 158 | 170 | t = "*string" | |
| 159 | - | c = fmt.Sprintf("core.NullableStringToPtr(%s)", n) | |
| 171 | + | c = fmt.Sprintf("%sPtr", n) | |
| 160 | 172 | cRef = c | |
| 173 | + | // Track this parameter for keepalive generation | |
| 174 | + | f.NullableStrings = append(f.NullableStrings, NullableStringParam{Name: n}) | |
| 161 | 175 | } | |
| 162 | 176 | ||
| 163 | 177 | switch k { | |
| @@ -227,7 +241,8 @@ func (f *funcArgsTemplate) AddPure(t string, n string, k Kind, isOut bool, nulla | |||
| 227 | 241 | if ctx == ArgsFromGoToC && nullable && isStringType(t) { | |
| 228 | 242 | f.UsesNullableHelper = true | |
| 229 | 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 | 248 | switch k { | |
| @@ -38,6 +38,14 @@ type CallbackParam struct { | |||||
| 38 | Nullable bool | 38 | 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 PureGo | 50 | // Pure are the arguments as passed directly to PureGo | ||
| 43 | // The pure Call is a special case that contains the arguments for a callback call | 51 | // 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 generation | 57 | // Callbacks tracks callback parameters for proper closure generation | ||
| 50 | Callbacks []CallbackParam | 58 | 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 bool | 64 | 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 type | 165 | // 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 = true | 169 | 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 = c | 172 | 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 = true | 242 | 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 ( | |||
| 29 | 29 | {{- if $HasDetailedSignals}} | |
| 30 | 30 | "fmt" | |
| 31 | 31 | {{- end}} | |
| 32 | + | {{- if $NeedsCore}} | |
| 33 | + | "runtime" | |
| 34 | + | {{- end}} | |
| 32 | 35 | {{- if .Records}} | |
| 33 | 36 | "structs" | |
| 34 | 37 | {{- end}} | |
| @@ -77,7 +80,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}} | |||
| 77 | 80 | {{.Doc}} | |
| 78 | 81 | func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 79 | 82 | {{.Ret.Preamble $NotGLib}} | |
| 80 | - | {{- /* Generate closure wrappers for callback parameters */}} | |
| 81 | 83 | {{range .Args.Callbacks}} | |
| 82 | 84 | var {{.Name}}Ref uintptr | |
| 83 | 85 | if {{.Name}} != nil { | |
| @@ -94,7 +96,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |||
| 94 | 96 | } | |
| 95 | 97 | } | |
| 96 | 98 | {{end}} | |
| 99 | + | {{range .Args.NullableStrings}} | |
| 100 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 101 | + | {{end}} | |
| 97 | 102 | {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}}) | |
| 103 | + | {{range .Args.NullableStrings}} | |
| 104 | + | runtime.KeepAlive({{.Name}}Bytes) | |
| 105 | + | {{end}} | |
| 98 | 106 | {{.Ret.Fmt $NotGObject}} | |
| 99 | 107 | } | |
| 100 | 108 | {{end}} | |
| @@ -106,7 +114,6 @@ var x{{$outer.Name}}{{.Name}} func(uintptr {{convc .Args.Pure.Types}}) {{.Ret.Ra | |||
| 106 | 114 | {{.Doc}} | |
| 107 | 115 | func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 108 | 116 | {{.Ret.Preamble $NotGLib}} | |
| 109 | - | {{- /* Generate closure wrappers for callback parameters */}} | |
| 110 | 117 | {{range .Args.Callbacks}} | |
| 111 | 118 | var {{.Name}}Ref uintptr | |
| 112 | 119 | if {{.Name}} != nil { | |
| @@ -123,7 +130,13 @@ func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |||
| 123 | 130 | } | |
| 124 | 131 | } | |
| 125 | 132 | {{end}} | |
| 133 | + | {{range .Args.NullableStrings}} | |
| 134 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 135 | + | {{end}} | |
| 126 | 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 | 140 | {{.Ret.Fmt $NotGObject}} | |
| 128 | 141 | } | |
| 129 | 142 | {{end}} | |
| @@ -204,7 +217,13 @@ func (x *{{.Name}}Base) SetGoPointer(ptr uintptr) { | |||
| 204 | 217 | {{.Doc}} | |
| 205 | 218 | func (x *{{$outer.Name}}Base) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 206 | 219 | {{.Ret.Preamble $NotGLib}} | |
| 220 | + | {{range .Args.NullableStrings}} | |
| 221 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 222 | + | {{end}} | |
| 207 | 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 | 227 | {{.Ret.Fmt $NotGObject}} | |
| 209 | 228 | } | |
| 210 | 229 | {{end}} | |
| @@ -284,7 +303,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}} | |||
| 284 | 303 | {{.Doc}} | |
| 285 | 304 | func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 286 | 305 | {{.Ret.Preamble $NotGLib}} | |
| 287 | - | {{- /* Generate closure wrappers for callback parameters */}} | |
| 288 | 306 | {{range .Args.Callbacks}} | |
| 289 | 307 | var {{.Name}}Ref uintptr | |
| 290 | 308 | if {{.Name}} != nil { | |
| @@ -301,7 +319,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |||
| 301 | 319 | } | |
| 302 | 320 | } | |
| 303 | 321 | {{end}} | |
| 322 | + | {{range .Args.NullableStrings}} | |
| 323 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 324 | + | {{end}} | |
| 304 | 325 | {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}}) | |
| 326 | + | {{range .Args.NullableStrings}} | |
| 327 | + | runtime.KeepAlive({{.Name}}Bytes) | |
| 328 | + | {{end}} | |
| 305 | 329 | {{.Ret.Fmt $NotGObject}} | |
| 306 | 330 | } | |
| 307 | 331 | {{end}} | |
| @@ -336,7 +360,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}} | |||
| 336 | 360 | {{.Doc}} | |
| 337 | 361 | func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 338 | 362 | {{.Ret.Preamble $NotGLib}} | |
| 339 | - | {{- /* Generate closure wrappers for callback parameters */}} | |
| 340 | 363 | {{range .Args.Callbacks}} | |
| 341 | 364 | var {{.Name}}Ref uintptr | |
| 342 | 365 | if {{.Name}} != nil { | |
| @@ -353,7 +376,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |||
| 353 | 376 | } | |
| 354 | 377 | } | |
| 355 | 378 | {{end}} | |
| 379 | + | {{range .Args.NullableStrings}} | |
| 380 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 381 | + | {{end}} | |
| 356 | 382 | {{if .Ret.Value}}cret :={{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}}) | |
| 383 | + | {{range .Args.NullableStrings}} | |
| 384 | + | runtime.KeepAlive({{.Name}}Bytes) | |
| 385 | + | {{end}} | |
| 357 | 386 | {{.Ret.Fmt $NotGObject}} | |
| 358 | 387 | } | |
| 359 | 388 | {{end}} | |
| @@ -365,7 +394,6 @@ var x{{$outer.Name}}{{.Name}} func(uintptr {{convc .Args.Pure.Types}}) {{.Ret.Ra | |||
| 365 | 394 | {{.Doc}} | |
| 366 | 395 | func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 367 | 396 | {{.Ret.Preamble $NotGLib}} | |
| 368 | - | {{- /* Generate closure wrappers for callback parameters */}} | |
| 369 | 397 | {{range .Args.Callbacks}} | |
| 370 | 398 | var {{.Name}}Ref uintptr | |
| 371 | 399 | if {{.Name}} != nil { | |
| @@ -382,7 +410,13 @@ func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |||
| 382 | 410 | } | |
| 383 | 411 | } | |
| 384 | 412 | {{end}} | |
| 413 | + | {{range .Args.NullableStrings}} | |
| 414 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 415 | + | {{end}} | |
| 385 | 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 | 420 | {{.Ret.Fmt $NotGObject}} | |
| 387 | 421 | } | |
| 388 | 422 | {{end}} | |
| @@ -481,7 +515,13 @@ func (x *{{$outer.Name}}) Connect{{.Name}}WithDetail(detail string, cb *func({{$ | |||
| 481 | 515 | {{.Doc}} | |
| 482 | 516 | func (x *{{$outer.Name}}) {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 483 | 517 | {{.Ret.Preamble $NotGLib}} | |
| 518 | + | {{range .Args.NullableStrings}} | |
| 519 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 520 | + | {{end}} | |
| 484 | 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 | 525 | {{.Ret.Fmt $NotGObject}} | |
| 486 | 526 | } | |
| 487 | 527 | {{end}} | |
| @@ -493,7 +533,6 @@ var x{{.Name}} func({{conv .Args.Pure.Types}}) {{.Ret.Raw}} | |||
| 493 | 533 | {{.Doc}} | |
| 494 | 534 | func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |
| 495 | 535 | {{.Ret.Preamble $NotGLib}} | |
| 496 | - | {{- /* Generate closure wrappers for callback parameters */}} | |
| 497 | 536 | {{range .Args.Callbacks}} | |
| 498 | 537 | var {{.Name}}Ref uintptr | |
| 499 | 538 | if {{.Name}} != nil { | |
| @@ -510,7 +549,13 @@ func {{.Name}}({{conv .Args.API.Full}}) {{.Ret.Return}} { | |||
| 510 | 549 | } | |
| 511 | 550 | } | |
| 512 | 551 | {{end}} | |
| 552 | + | {{range .Args.NullableStrings}} | |
| 553 | + | {{.Name}}Ptr, {{.Name}}Bytes := core.NullableStringToPtr({{.Name}}) | |
| 554 | + | {{end}} | |
| 513 | 555 | {{if .Ret.Value}}cret := {{end}}x{{.Name}}({{convd .Args.API.CallWithRefs}}) | |
| 556 | + | {{range .Args.NullableStrings}} | |
| 557 | + | runtime.KeepAlive({{.Name}}Bytes) | |
| 558 | + | {{end}} | |
| 514 | 559 | {{.Ret.Fmt $NotGObject}} | |
| 515 | 560 | } | |
| 516 | 561 | {{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 uintptr | 84 | 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 uintptr | 118 | 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 uintptr | 307 | 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 uintptr | 364 | 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 uintptr | 398 | 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 uintptr | 537 | 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}} | ||