chore: switch purego dependency to bnema/purego fork
Replace local path replace directive with GitHub URL pointing to bnema/purego@91aa177 to avoid accidental pushes to upstream.
- commit
- 8b029581aa8aebd90aa84a2b638058062afa9bdd
- author
- brice · · 2026-03-23 19:51 UTC
- parent
- f14f9b6
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
51 files · +1860 -488
M go.mod +2 -0
| @@ -3,3 +3,5 @@ module github.com/bnema/puregotk | |||
| 3 | 3 | go 1.26.1 | |
| 4 | 4 | ||
| 5 | 5 | require github.com/ebitengine/purego v0.10.0 | |
| 6 | + | ||
| 7 | + | replace github.com/ebitengine/purego => github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704 | |
| @@ -3,3 +3,5 @@ module github.com/bnema/puregotk | |||||
| 3 | go 1.26.1 | 3 | go 1.26.1 | ||
| 4 | 4 | ||||
| 5 | require github.com/ebitengine/purego v0.10.0 | 5 | require github.com/ebitengine/purego v0.10.0 | ||
| 6 | + | ||||
| 7 | + | replace github.com/ebitengine/purego => github.com/bnema/purego v0.0.0-20260323095903-91aa177a2704 | |||
M go.sum +2 -2 generated file: collapsed
M vendor/github.com/ebitengine/purego/README.md +3 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/dlfcn_nocgo_netbsd.go +2 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/func.go +220 -107 generated file: collapsed
A vendor/github.com/ebitengine/purego/hostlayout_go123.go +12 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/hostlayout_nogo123.go +11 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/abi_riscv64.h +72 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/asm_riscv64.s +14 -55 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd.go +4 -25 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux.go +4 -25 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go +4 -25 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go +2 -2 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/linux.go +184 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go +1 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_386.s +18 -4 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s +1 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm.s +44 -3 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s +1 -4 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_linux_386.s +78 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_linux_amd64.s +69 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_linux_arm.s +69 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_linux_arm64.s +60 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_linux_loong64.s +60 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_linux_ppc64le.s +69 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_linux_riscv64.s +60 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_loong64.s +1 -11 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_ppc64le.s +30 -129 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_riscv64.s +11 -7 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_linux.go +110 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_linux.s +30 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_386.go +12 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_amd64.go +162 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_arm.go +8 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_arm64.go +203 -7 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_loong64.go +9 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_ppc64le.go +9 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_riscv64.go +9 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/struct_s390x.go +9 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/sys_amd64.s +16 -16 generated file: collapsed
M vendor/github.com/ebitengine/purego/sys_arm64.s +2 -1 generated file: collapsed
M vendor/github.com/ebitengine/purego/sys_unix_arm64.s +8 -3 generated file: collapsed
M vendor/github.com/ebitengine/purego/sys_unix_loong64.s +9 -5 generated file: collapsed
M vendor/github.com/ebitengine/purego/syscall.go +21 -0 generated file: collapsed
M vendor/github.com/ebitengine/purego/syscall_32bit.go +21 -0 generated file: collapsed
A vendor/github.com/ebitengine/purego/syscall_notstackargs.go +38 -0 generated file: collapsed
R vendor/github.com/ebitengine/purego/syscall_sysv_stackargs.go → vendor/github.com/ebitengine/purego/syscall_stackargs.go +13 -3 generated file: collapsed · renamed, 54% similar
D vendor/github.com/ebitengine/purego/syscall_sysv_others.go +0 -28 generated file: collapsed
R vendor/github.com/ebitengine/purego/syscall_sysv.go → vendor/github.com/ebitengine/purego/syscall_unix.go +53 -18 renamed, 85% similar
| @@ -55,9 +55,10 @@ func NewCallback(fn any) uintptr { | |||
| 55 | 55 | const maxCB = 2000 | |
| 56 | 56 | ||
| 57 | 57 | var cbs struct { | |
| 58 | - | lock sync.Mutex | |
| 59 | - | numFn int // the number of functions currently in cbs.funcs | |
| 60 | - | funcs [maxCB]reflect.Value // the saved callbacks | |
| 58 | + | lock sync.RWMutex | |
| 59 | + | numFn int // the number of functions currently in cbs.funcs | |
| 60 | + | funcs [maxCB]reflect.Value // the saved callbacks | |
| 61 | + | argPools [maxCB]*sync.Pool // pre-allocated argument buffers per callback | |
| 61 | 62 | } | |
| 62 | 63 | ||
| 63 | 64 | func compileCallback(fn any) uintptr { | |
| @@ -76,7 +77,9 @@ func compileCallback(fn any) uintptr { | |||
| 76 | 77 | if i == 0 && in.AssignableTo(reflect.TypeOf(CDecl{})) { | |
| 77 | 78 | continue | |
| 78 | 79 | } | |
| 79 | - | fallthrough | |
| 80 | + | ensureStructSupported() | |
| 81 | + | checkStructFieldsSupported(in) | |
| 82 | + | continue | |
| 80 | 83 | case reflect.Interface, reflect.Func, reflect.Slice, | |
| 81 | 84 | reflect.Chan, reflect.Complex64, reflect.Complex128, | |
| 82 | 85 | reflect.String, reflect.Map, reflect.Invalid: | |
| @@ -89,7 +92,7 @@ output: | |||
| 89 | 92 | switch ty.Out(0).Kind() { | |
| 90 | 93 | case reflect.Pointer, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, | |
| 91 | 94 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, | |
| 92 | - | reflect.Bool, reflect.UnsafePointer: | |
| 95 | + | reflect.Bool, reflect.UnsafePointer, reflect.Struct: | |
| 93 | 96 | break output | |
| 94 | 97 | } | |
| 95 | 98 | panic("purego: unsupported return type: " + ty.String()) | |
| @@ -101,9 +104,16 @@ output: | |||
| 101 | 104 | if cbs.numFn >= maxCB { | |
| 102 | 105 | panic("purego: the maximum number of callbacks has been reached") | |
| 103 | 106 | } | |
| 104 | - | cbs.funcs[cbs.numFn] = val | |
| 107 | + | index := cbs.numFn | |
| 108 | + | cbs.funcs[index] = val | |
| 109 | + | numIn := ty.NumIn() | |
| 110 | + | cbs.argPools[index] = &sync.Pool{ | |
| 111 | + | New: func() any { | |
| 112 | + | return make([]reflect.Value, numIn) | |
| 113 | + | }, | |
| 114 | + | } | |
| 105 | 115 | cbs.numFn++ | |
| 106 | - | return callbackasmAddr(cbs.numFn - 1) | |
| 116 | + | return callbackasmAddr(index) | |
| 107 | 117 | } | |
| 108 | 118 | ||
| 109 | 119 | const ptrSize = unsafe.Sizeof((*int)(nil)) | |
| @@ -125,11 +135,18 @@ var callbackWrap_call = callbackWrap | |||
| 125 | 135 | // callbackWrap is called by assembly code which determines which Go function to call. | |
| 126 | 136 | // This function takes the arguments and passes them to the Go function and returns the result. | |
| 127 | 137 | func callbackWrap(a *callbackArgs) { | |
| 128 | - | cbs.lock.Lock() | |
| 138 | + | cbs.lock.RLock() | |
| 129 | 139 | fn := cbs.funcs[a.index] | |
| 130 | - | cbs.lock.Unlock() | |
| 140 | + | pool := cbs.argPools[a.index] | |
| 141 | + | cbs.lock.RUnlock() | |
| 131 | 142 | fnType := fn.Type() | |
| 132 | - | args := make([]reflect.Value, fnType.NumIn()) | |
| 143 | + | args := pool.Get().([]reflect.Value) | |
| 144 | + | defer func() { | |
| 145 | + | for i := range args { | |
| 146 | + | args[i] = reflect.Value{} | |
| 147 | + | } | |
| 148 | + | pool.Put(args) | |
| 149 | + | }() | |
| 133 | 150 | frame := (*[callbackMaxFrame]uintptr)(a.args) | |
| 134 | 151 | // stackFrame points to stack-passed arguments. On most architectures this is | |
| 135 | 152 | // contiguous with frame (after register args), but on ppc64le it's separate. | |
| @@ -142,6 +159,14 @@ func callbackWrap(a *callbackArgs) { | |||
| 142 | 159 | // This distinction matters on ARM32 where float64 uses 2 slots (32-bit registers). | |
| 143 | 160 | var floatsN int | |
| 144 | 161 | var intsN int | |
| 162 | + | // On amd64/loong64/ppc64le/riscv64/s390x, when returning a struct larger than | |
| 163 | + | // maxRegAllocStructSize, the caller passes a hidden pointer in the first integer | |
| 164 | + | // register. Skip it to avoid misreading it as the first function argument. | |
| 165 | + | if (runtime.GOARCH == "amd64" || runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") && | |
| 166 | + | fnType.NumOut() == 1 && fnType.Out(0).Kind() == reflect.Struct && | |
| 167 | + | fnType.Out(0).Size() > maxRegAllocStructSize { | |
| 168 | + | intsN = 1 | |
| 169 | + | } | |
| 145 | 170 | // stackSlot points to the index into frame (or stackFrame) of the current stack element. | |
| 146 | 171 | // When stackFrame is nil, stack begins after float and integer registers in frame. | |
| 147 | 172 | // When stackFrame is not nil (ppc64le), stackSlot indexes into stackFrame starting at 0. | |
| @@ -187,8 +212,16 @@ func callbackWrap(a *callbackArgs) { | |||
| 187 | 212 | } | |
| 188 | 213 | floatsN += slots | |
| 189 | 214 | case reflect.Struct: | |
| 190 | - | // This is the CDecl field | |
| 191 | - | args[i] = reflect.Zero(inType) | |
| 215 | + | if i == 0 && inType.AssignableTo(reflect.TypeOf(CDecl{})) { | |
| 216 | + | args[i] = reflect.Zero(inType) | |
| 217 | + | continue | |
| 218 | + | } | |
| 219 | + | if inType.Size() == 0 { | |
| 220 | + | args[i] = reflect.New(inType).Elem() | |
| 221 | + | continue | |
| 222 | + | } | |
| 223 | + | args[i] = getCallbackStruct(inType, a.args, &floatsN, &intsN, &stackSlot, &stackByteOffset) | |
| 224 | + | continue | |
| 192 | 225 | default: | |
| 193 | 226 | slots = int((inType.Size() + ptrSize - 1) / ptrSize) | |
| 194 | 227 | if intsN+slots > numOfIntegerRegisters() { | |
| @@ -225,19 +258,21 @@ func callbackWrap(a *callbackArgs) { | |||
| 225 | 258 | if len(ret) > 0 { | |
| 226 | 259 | switch k := ret[0].Kind(); k { | |
| 227 | 260 | case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uintptr: | |
| 228 | - | a.result = uintptr(ret[0].Uint()) | |
| 261 | + | a.result[0] = uintptr(ret[0].Uint()) | |
| 229 | 262 | case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8: | |
| 230 | - | a.result = uintptr(ret[0].Int()) | |
| 263 | + | a.result[0] = uintptr(ret[0].Int()) | |
| 231 | 264 | case reflect.Bool: | |
| 232 | 265 | if ret[0].Bool() { | |
| 233 | - | a.result = 1 | |
| 266 | + | a.result[0] = 1 | |
| 234 | 267 | } else { | |
| 235 | - | a.result = 0 | |
| 268 | + | a.result[0] = 0 | |
| 236 | 269 | } | |
| 237 | 270 | case reflect.Pointer: | |
| 238 | - | a.result = ret[0].Pointer() | |
| 271 | + | a.result[0] = ret[0].Pointer() | |
| 239 | 272 | case reflect.UnsafePointer: | |
| 240 | - | a.result = ret[0].Pointer() | |
| 273 | + | a.result[0] = ret[0].Pointer() | |
| 274 | + | case reflect.Struct: | |
| 275 | + | setStruct(a, ret[0]) | |
| 241 | 276 | default: | |
| 242 | 277 | panic("purego: unsupported kind: " + k.String()) | |
| 243 | 278 | } | |
| @@ -55,9 +55,10 @@ func NewCallback(fn any) uintptr { | |||||
| 55 | const maxCB = 2000 | 55 | const maxCB = 2000 | ||
| 56 | 56 | ||||
| 57 | var cbs struct { | 57 | var cbs struct { | ||
| 58 | - | lock sync.Mutex | 58 | + | lock sync.RWMutex |
| 59 | - | numFn int // the number of functions currently in cbs.funcs | 59 | + | numFn int // the number of functions currently in cbs.funcs |
| 60 | - | funcs [maxCB]reflect.Value // the saved callbacks | 60 | + | funcs [maxCB]reflect.Value // the saved callbacks |
| 61 | + | argPools [maxCB]*sync.Pool // pre-allocated argument buffers per callback | |||
| 61 | } | 62 | } | ||
| 62 | 63 | ||||
| 63 | func compileCallback(fn any) uintptr { | 64 | func compileCallback(fn any) uintptr { | ||
| @@ -76,7 +77,9 @@ func compileCallback(fn any) uintptr { | |||||
| 76 | if i == 0 && in.AssignableTo(reflect.TypeOf(CDecl{})) { | 77 | if i == 0 && in.AssignableTo(reflect.TypeOf(CDecl{})) { | ||
| 77 | continue | 78 | continue | ||
| 78 | } | 79 | } | ||
| 79 | - | fallthrough | 80 | + | ensureStructSupported() |
| 81 | + | checkStructFieldsSupported(in) | |||
| 82 | + | continue | |||
| 80 | case reflect.Interface, reflect.Func, reflect.Slice, | 83 | case reflect.Interface, reflect.Func, reflect.Slice, | ||
| 81 | reflect.Chan, reflect.Complex64, reflect.Complex128, | 84 | reflect.Chan, reflect.Complex64, reflect.Complex128, | ||
| 82 | reflect.String, reflect.Map, reflect.Invalid: | 85 | reflect.String, reflect.Map, reflect.Invalid: | ||
| @@ -89,7 +92,7 @@ output: | |||||
| 89 | switch ty.Out(0).Kind() { | 92 | switch ty.Out(0).Kind() { | ||
| 90 | case reflect.Pointer, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, | 93 | case reflect.Pointer, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, | ||
| 91 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, | 94 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, | ||
| 92 | - | reflect.Bool, reflect.UnsafePointer: | 95 | + | reflect.Bool, reflect.UnsafePointer, reflect.Struct: |
| 93 | break output | 96 | break output | ||
| 94 | } | 97 | } | ||
| 95 | panic("purego: unsupported return type: " + ty.String()) | 98 | panic("purego: unsupported return type: " + ty.String()) | ||
| @@ -101,9 +104,16 @@ output: | |||||
| 101 | if cbs.numFn >= maxCB { | 104 | if cbs.numFn >= maxCB { | ||
| 102 | panic("purego: the maximum number of callbacks has been reached") | 105 | panic("purego: the maximum number of callbacks has been reached") | ||
| 103 | } | 106 | } | ||
| 104 | - | cbs.funcs[cbs.numFn] = val | 107 | + | index := cbs.numFn |
| 108 | + | cbs.funcs[index] = val | |||
| 109 | + | numIn := ty.NumIn() | |||
| 110 | + | cbs.argPools[index] = &sync.Pool{ | |||
| 111 | + | New: func() any { | |||
| 112 | + | return make([]reflect.Value, numIn) | |||
| 113 | + | }, | |||
| 114 | + | } | |||
| 105 | cbs.numFn++ | 115 | cbs.numFn++ | ||
| 106 | - | return callbackasmAddr(cbs.numFn - 1) | 116 | + | return callbackasmAddr(index) |
| 107 | } | 117 | } | ||
| 108 | 118 | ||||
| 109 | const ptrSize = unsafe.Sizeof((*int)(nil)) | 119 | const ptrSize = unsafe.Sizeof((*int)(nil)) | ||
| @@ -125,11 +135,18 @@ var callbackWrap_call = callbackWrap | |||||
| 125 | // callbackWrap is called by assembly code which determines which Go function to call. | 135 | // callbackWrap is called by assembly code which determines which Go function to call. | ||
| 126 | // This function takes the arguments and passes them to the Go function and returns the result. | 136 | // This function takes the arguments and passes them to the Go function and returns the result. | ||
| 127 | func callbackWrap(a *callbackArgs) { | 137 | func callbackWrap(a *callbackArgs) { | ||
| 128 | - | cbs.lock.Lock() | 138 | + | cbs.lock.RLock() |
| 129 | fn := cbs.funcs[a.index] | 139 | fn := cbs.funcs[a.index] | ||
| 130 | - | cbs.lock.Unlock() | 140 | + | pool := cbs.argPools[a.index] |
| 141 | + | cbs.lock.RUnlock() | |||
| 131 | fnType := fn.Type() | 142 | fnType := fn.Type() | ||
| 132 | - | args := make([]reflect.Value, fnType.NumIn()) | 143 | + | args := pool.Get().([]reflect.Value) |
| 144 | + | defer func() { | |||
| 145 | + | for i := range args { | |||
| 146 | + | args[i] = reflect.Value{} | |||
| 147 | + | } | |||
| 148 | + | pool.Put(args) | |||
| 149 | + | }() | |||
| 133 | frame := (*[callbackMaxFrame]uintptr)(a.args) | 150 | frame := (*[callbackMaxFrame]uintptr)(a.args) | ||
| 134 | // stackFrame points to stack-passed arguments. On most architectures this is | 151 | // stackFrame points to stack-passed arguments. On most architectures this is | ||
| 135 | // contiguous with frame (after register args), but on ppc64le it's separate. | 152 | // contiguous with frame (after register args), but on ppc64le it's separate. | ||
| @@ -142,6 +159,14 @@ func callbackWrap(a *callbackArgs) { | |||||
| 142 | // This distinction matters on ARM32 where float64 uses 2 slots (32-bit registers). | 159 | // This distinction matters on ARM32 where float64 uses 2 slots (32-bit registers). | ||
| 143 | var floatsN int | 160 | var floatsN int | ||
| 144 | var intsN int | 161 | var intsN int | ||
| 162 | + | // On amd64/loong64/ppc64le/riscv64/s390x, when returning a struct larger than | |||
| 163 | + | // maxRegAllocStructSize, the caller passes a hidden pointer in the first integer | |||
| 164 | + | // register. Skip it to avoid misreading it as the first function argument. | |||
| 165 | + | if (runtime.GOARCH == "amd64" || runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") && | |||
| 166 | + | fnType.NumOut() == 1 && fnType.Out(0).Kind() == reflect.Struct && | |||
| 167 | + | fnType.Out(0).Size() > maxRegAllocStructSize { | |||
| 168 | + | intsN = 1 | |||
| 169 | + | } | |||
| 145 | // stackSlot points to the index into frame (or stackFrame) of the current stack element. | 170 | // stackSlot points to the index into frame (or stackFrame) of the current stack element. | ||
| 146 | // When stackFrame is nil, stack begins after float and integer registers in frame. | 171 | // When stackFrame is nil, stack begins after float and integer registers in frame. | ||
| 147 | // When stackFrame is not nil (ppc64le), stackSlot indexes into stackFrame starting at 0. | 172 | // When stackFrame is not nil (ppc64le), stackSlot indexes into stackFrame starting at 0. | ||
| @@ -187,8 +212,16 @@ func callbackWrap(a *callbackArgs) { | |||||
| 187 | } | 212 | } | ||
| 188 | floatsN += slots | 213 | floatsN += slots | ||
| 189 | case reflect.Struct: | 214 | case reflect.Struct: | ||
| 190 | - | // This is the CDecl field | 215 | + | if i == 0 && inType.AssignableTo(reflect.TypeOf(CDecl{})) { |
| 191 | - | args[i] = reflect.Zero(inType) | 216 | + | args[i] = reflect.Zero(inType) |
| 217 | + | continue | |||
| 218 | + | } | |||
| 219 | + | if inType.Size() == 0 { | |||
| 220 | + | args[i] = reflect.New(inType).Elem() | |||
| 221 | + | continue | |||
| 222 | + | } | |||
| 223 | + | args[i] = getCallbackStruct(inType, a.args, &floatsN, &intsN, &stackSlot, &stackByteOffset) | |||
| 224 | + | continue | |||
| 192 | default: | 225 | default: | ||
| 193 | slots = int((inType.Size() + ptrSize - 1) / ptrSize) | 226 | slots = int((inType.Size() + ptrSize - 1) / ptrSize) | ||
| 194 | if intsN+slots > numOfIntegerRegisters() { | 227 | if intsN+slots > numOfIntegerRegisters() { | ||
| @@ -225,19 +258,21 @@ func callbackWrap(a *callbackArgs) { | |||||
| 225 | if len(ret) > 0 { | 258 | if len(ret) > 0 { | ||
| 226 | switch k := ret[0].Kind(); k { | 259 | switch k := ret[0].Kind(); k { | ||
| 227 | case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uintptr: | 260 | case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uintptr: | ||
| 228 | - | a.result = uintptr(ret[0].Uint()) | 261 | + | a.result[0] = uintptr(ret[0].Uint()) |
| 229 | case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8: | 262 | case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8: | ||
| 230 | - | a.result = uintptr(ret[0].Int()) | 263 | + | a.result[0] = uintptr(ret[0].Int()) |
| 231 | case reflect.Bool: | 264 | case reflect.Bool: | ||
| 232 | if ret[0].Bool() { | 265 | if ret[0].Bool() { | ||
| 233 | - | a.result = 1 | 266 | + | a.result[0] = 1 |
| 234 | } else { | 267 | } else { | ||
| 235 | - | a.result = 0 | 268 | + | a.result[0] = 0 |
| 236 | } | 269 | } | ||
| 237 | case reflect.Pointer: | 270 | case reflect.Pointer: | ||
| 238 | - | a.result = ret[0].Pointer() | 271 | + | a.result[0] = ret[0].Pointer() |
| 239 | case reflect.UnsafePointer: | 272 | case reflect.UnsafePointer: | ||
| 240 | - | a.result = ret[0].Pointer() | 273 | + | a.result[0] = ret[0].Pointer() |
| 274 | + | case reflect.Struct: | |||
| 275 | + | setStruct(a, ret[0]) | |||
| 241 | default: | 276 | default: | ||
| 242 | panic("purego: unsupported kind: " + k.String()) | 277 | panic("purego: unsupported kind: " + k.String()) | ||
| 243 | } | 278 | } | ||