detached 1ff8716

Add RegisterFunc on unsupported platforms (#234)

Implement Cgo fallback for RegisterFunc. Add testing for windows and Linux 386 to GitHub actions.

Closes #230
commit
1ff8716e2490fb1e191cb96bfffdb0ff64d8b7f5
author
TotallyGamerJet · · 2024-04-29 11:49 UTC
committer
GitHub · · 2024-04-29 11:49 UTC
parent
de702ef
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
38 files · +205 -72
M .github/workflows/test.yml +12 -1
@@ -100,7 +100,18 @@ jobs:
100100 go env -u CC
101101 go env -u CXX
102102
103- # TODO: add Windows 386 tests
103+ - name: go test (Windows 386)
104+ if: runner.os == 'Windows'
105+ run: |
106+ env CGO_ENABLED=0 GOARCH=386 go test -shuffle=on -v -count=10 ./...
107+ env CGO_ENABLED=1 GOARCH=386 go test -shuffle=on -v -count=10 ./...
108+
109+ - name: go test (Linux 386)
110+ if: runner.os == 'Linux'
111+ run: |
112+ sudo apt-get install gcc-multilib
113+ sudo apt-get install g++-multilib
114+ env CGO_ENABLED=1 GOARCH=386 go test -shuffle=on -v -count=10 ./...
104115
105116 - name: go test race
106117 if: ${{ !startsWith(matrix.go, '1.18.') && !startsWith(matrix.go, '1.19.') }}
@@ -100,7 +100,18 @@ jobs:
100 go env -u CC100 go env -u CC
101 go env -u CXX101 go env -u CXX
102 102
103- # TODO: add Windows 386 tests103+ - name: go test (Windows 386)
104+ if: runner.os == 'Windows'
105+ run: |
106+ env CGO_ENABLED=0 GOARCH=386 go test -shuffle=on -v -count=10 ./...
107+ env CGO_ENABLED=1 GOARCH=386 go test -shuffle=on -v -count=10 ./...
108+
109+ - name: go test (Linux 386)
110+ if: runner.os == 'Linux'
111+ run: |
112+ sudo apt-get install gcc-multilib
113+ sudo apt-get install g++-multilib
114+ env CGO_ENABLED=1 GOARCH=386 go test -shuffle=on -v -count=10 ./...
104 115
105 - name: go test race116 - name: go test race
106 if: ${{ !startsWith(matrix.go, '1.18.') && !startsWith(matrix.go, '1.19.') }}117 if: ${{ !startsWith(matrix.go, '1.18.') && !startsWith(matrix.go, '1.19.') }}
M callback_test.go +28 -1
@@ -1,11 +1,12 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
33
4-//go:build darwin || (linux && (!cgo || amd64 || arm64))
4+//go:build darwin || (linux && (amd64 || arm64))
55
66 package purego_test
77
88 import (
9+ "fmt"
910 "os"
1011 "path/filepath"
1112 "testing"
@@ -146,3 +147,29 @@ func TestNewCallbackFloat32AndFloat64(t *testing.T) {
146147 t.Errorf("cbTotalF64 not correct got %f but wanted %f", cbTotalF64, expectedCbTotalF64)
147148 }
148149 }
150+
151+func ExampleNewCallback() {
152+ cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int {
153+ fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
154+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15
155+ })
156+
157+ var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int
158+ purego.RegisterFunc(&fn, cb)
159+
160+ ret := fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
161+ fmt.Println(ret)
162+
163+ // Output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
164+ // 120
165+}
166+
167+func ExampleNewCallback_cdecl() {
168+ fn := func(_ purego.CDecl, a int) {
169+ fmt.Println(a)
170+ }
171+ cb := purego.NewCallback(fn)
172+ purego.SyscallN(cb, 83)
173+
174+ // Output: 83
175+}
@@ -1,11 +1,12 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors
3 3
4-//go:build darwin || (linux && (!cgo || amd64 || arm64))4+//go:build darwin || (linux && (amd64 || arm64))
5 5
6 package purego_test6 package purego_test
7 7
8 import (8 import (
9+ "fmt"
9 "os"10 "os"
10 "path/filepath"11 "path/filepath"
11 "testing"12 "testing"
@@ -146,3 +147,29 @@ func TestNewCallbackFloat32AndFloat64(t *testing.T) {
146 t.Errorf("cbTotalF64 not correct got %f but wanted %f", cbTotalF64, expectedCbTotalF64)147 t.Errorf("cbTotalF64 not correct got %f but wanted %f", cbTotalF64, expectedCbTotalF64)
147 }148 }
148 }149 }
150+
151+func ExampleNewCallback() {
152+ cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int {
153+ fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
154+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15
155+ })
156+
157+ var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int
158+ purego.RegisterFunc(&fn, cb)
159+
160+ ret := fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
161+ fmt.Println(ret)
162+
163+ // Output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
164+ // 120
165+}
166+
167+func ExampleNewCallback_cdecl() {
168+ fn := func(_ purego.CDecl, a int) {
169+ fmt.Println(a)
170+ }
171+ cb := purego.NewCallback(fn)
172+ purego.SyscallN(cb, 83)
173+
174+ // Output: 83
175+}
M dlfcn.go +0 -5
@@ -63,11 +63,6 @@ func Dlclose(handle uintptr) error {
6363 return nil
6464 }
6565
66-//go:linkname openLibrary openLibrary
67-func openLibrary(name string) (uintptr, error) {
68- return Dlopen(name, RTLD_NOW|RTLD_GLOBAL)
69-}
70-
7166 func loadSymbol(handle uintptr, name string) (uintptr, error) {
7267 return Dlsym(handle, name)
7368 }
@@ -63,11 +63,6 @@ func Dlclose(handle uintptr) error {
63 return nil63 return nil
64 }64 }
65 65
66-//go:linkname openLibrary openLibrary
67-func openLibrary(name string) (uintptr, error) {
68- return Dlopen(name, RTLD_NOW|RTLD_GLOBAL)
69-}
70-
71 func loadSymbol(handle uintptr, name string) (uintptr, error) {66 func loadSymbol(handle uintptr, name string) (uintptr, error) {
72 return Dlsym(handle, name)67 return Dlsym(handle, name)
73 }68 }
M dlfcn_test.go +3 -1
@@ -59,7 +59,9 @@ func buildSharedLib(compilerEnv, libFile string, sources ...string) error {
5959 } else {
6060 args = []string{"-shared", "-Wall", "-Werror", "-o", libFile}
6161 }
62-
62+ if runtime.GOARCH == "386" {
63+ args = append(args, "-m32")
64+ }
6365 // macOS arm64 can run amd64 tests through Rossetta.
6466 // Build the shared library based on the GOARCH and not
6567 // the default behavior of the compiler.
@@ -59,7 +59,9 @@ func buildSharedLib(compilerEnv, libFile string, sources ...string) error {
59 } else {59 } else {
60 args = []string{"-shared", "-Wall", "-Werror", "-o", libFile}60 args = []string{"-shared", "-Wall", "-Werror", "-o", libFile}
61 }61 }
62-62+ if runtime.GOARCH == "386" {
63+ args = append(args, "-m32")
64+ }
63 // macOS arm64 can run amd64 tests through Rossetta.65 // macOS arm64 can run amd64 tests through Rossetta.
64 // Build the shared library based on the GOARCH and not66 // Build the shared library based on the GOARCH and not
65 // the default behavior of the compiler.67 // the default behavior of the compiler.
M func.go +22 -8
@@ -117,6 +117,10 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
117117 if cfn == 0 {
118118 panic("purego: cfn is nil")
119119 }
120+ if ty.NumOut() == 1 && (ty.Out(0).Kind() == reflect.Float32 || ty.Out(0).Kind() == reflect.Float64) &&
121+ runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
122+ panic("purego: float returns are not supported")
123+ }
120124 {
121125 // this code checks how many registers and stack this function will use
122126 // to avoid crashing with too many arguments
@@ -126,9 +130,22 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
126130 for i := 0; i < ty.NumIn(); i++ {
127131 arg := ty.In(i)
128132 switch arg.Kind() {
133+ case reflect.Func:
134+ // This only does preliminary testing to ensure the CDecl argument
135+ // is the first argument. Full testing is done when the callback is actually
136+ // created in NewCallback.
137+ for j := 0; j < arg.NumIn(); j++ {
138+ in := arg.In(j)
139+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
140+ continue
141+ }
142+ if j != 0 {
143+ panic("purego: CDecl must be the first argument")
144+ }
145+ }
129146 case reflect.String, reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
130- reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Ptr, reflect.UnsafePointer, reflect.Slice,
131- reflect.Func, reflect.Bool:
147+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Ptr, reflect.UnsafePointer,
148+ reflect.Slice, reflect.Bool:
132149 if ints < numOfIntegerRegisters() {
133150 ints++
134151 } else {
@@ -413,12 +430,9 @@ func numOfIntegerRegisters() int {
413430 return 8
414431 case "amd64":
415432 return 6
416- // TODO: figure out why 386 tests are not working
417- /*case "386":
418- return 0
419- case "arm":
420- return 4*/
421433 default:
422- panic("purego: unknown GOARCH (" + runtime.GOARCH + ")")
434+ // since this platform isn't supported and can therefore only access
435+ // integer registers it is fine to return the maxArgs
436+ return maxArgs
423437 }
424438 }
@@ -117,6 +117,10 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
117 if cfn == 0 {117 if cfn == 0 {
118 panic("purego: cfn is nil")118 panic("purego: cfn is nil")
119 }119 }
120+ if ty.NumOut() == 1 && (ty.Out(0).Kind() == reflect.Float32 || ty.Out(0).Kind() == reflect.Float64) &&
121+ runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
122+ panic("purego: float returns are not supported")
123+ }
120 {124 {
121 // this code checks how many registers and stack this function will use125 // this code checks how many registers and stack this function will use
122 // to avoid crashing with too many arguments126 // to avoid crashing with too many arguments
@@ -126,9 +130,22 @@ func RegisterFunc(fptr interface{}, cfn uintptr) {
126 for i := 0; i < ty.NumIn(); i++ {130 for i := 0; i < ty.NumIn(); i++ {
127 arg := ty.In(i)131 arg := ty.In(i)
128 switch arg.Kind() {132 switch arg.Kind() {
133+ case reflect.Func:
134+ // This only does preliminary testing to ensure the CDecl argument
135+ // is the first argument. Full testing is done when the callback is actually
136+ // created in NewCallback.
137+ for j := 0; j < arg.NumIn(); j++ {
138+ in := arg.In(j)
139+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
140+ continue
141+ }
142+ if j != 0 {
143+ panic("purego: CDecl must be the first argument")
144+ }
145+ }
129 case reflect.String, reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,146 case reflect.String, reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
130- reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Ptr, reflect.UnsafePointer, reflect.Slice,147+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Ptr, reflect.UnsafePointer,
131- reflect.Func, reflect.Bool:148+ reflect.Slice, reflect.Bool:
132 if ints < numOfIntegerRegisters() {149 if ints < numOfIntegerRegisters() {
133 ints++150 ints++
134 } else {151 } else {
@@ -413,12 +430,9 @@ func numOfIntegerRegisters() int {
413 return 8430 return 8
414 case "amd64":431 case "amd64":
415 return 6432 return 6
416- // TODO: figure out why 386 tests are not working
417- /*case "386":
418- return 0
419- case "arm":
420- return 4*/
421 default:433 default:
422- panic("purego: unknown GOARCH (" + runtime.GOARCH + ")")434+ // since this platform isn't supported and can therefore only access
435+ // integer registers it is fine to return the maxArgs
436+ return maxArgs
423 }437 }
424 }438 }
M func_test.go +20 -27
@@ -10,13 +10,9 @@ import (
1010 "unsafe"
1111
1212 "github.com/ebitengine/purego"
13+ "github.com/ebitengine/purego/internal/load"
1314 )
1415
15-// This is an internal OS-dependent function for getting the handle to a library
16-//
17-//go:linkname openLibrary openLibrary
18-func openLibrary(name string) (uintptr, error)
19-
2016 func getSystemLibrary() (string, error) {
2117 switch runtime.GOOS {
2218 case "darwin":
@@ -37,7 +33,7 @@ func TestRegisterFunc(t *testing.T) {
3733 if err != nil {
3834 t.Fatalf("couldn't get system library: %s", err)
3935 }
40- libc, err := openLibrary(library)
36+ libc, err := load.OpenLibrary(library)
4137 if err != nil {
4238 t.Fatalf("failed to dlopen: %s", err)
4339 }
@@ -46,38 +42,26 @@ func TestRegisterFunc(t *testing.T) {
4642 puts("Calling C from from Go without Cgo!")
4743 }
4844
49-func ExampleNewCallback() {
50- cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int {
51- fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
52- return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15
53- })
54-
55- var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int
56- purego.RegisterFunc(&fn, cb)
57-
58- ret := fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
59- fmt.Println(ret)
60-
61- // Output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
62- // 120
63-}
64-
6545 func Test_qsort(t *testing.T) {
46+ if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
47+ t.Skip("Platform doesn't support Floats")
48+ return
49+ }
6650 library, err := getSystemLibrary()
6751 if err != nil {
6852 t.Fatalf("couldn't get system library: %s", err)
6953 }
70- libc, err := openLibrary(library)
54+ libc, err := load.OpenLibrary(library)
7155 if err != nil {
7256 t.Fatalf("failed to dlopen: %s", err)
7357 }
7458
7559 data := []int{88, 56, 100, 2, 25}
7660 sorted := []int{2, 25, 56, 88, 100}
77- compare := func(a, b *int) int {
61+ compare := func(_ purego.CDecl, a, b *int) int {
7862 return *a - *b
7963 }
80- var qsort func(data []int, nitms uintptr, size uintptr, compar func(a, b *int) int)
64+ var qsort func(data []int, nitms uintptr, size uintptr, compar func(_ purego.CDecl, a, b *int) int)
8165 purego.RegisterLibFunc(&qsort, libc, "qsort")
8266 qsort(data, uintptr(len(data)), unsafe.Sizeof(int(0)), compare)
8367 for i := range data {
@@ -88,11 +72,15 @@ func Test_qsort(t *testing.T) {
8872 }
8973
9074 func TestRegisterFunc_Floats(t *testing.T) {
75+ if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
76+ t.Skip("Platform doesn't support Floats")
77+ return
78+ }
9179 library, err := getSystemLibrary()
9280 if err != nil {
9381 t.Fatalf("couldn't get system library: %s", err)
9482 }
95- libc, err := openLibrary(library)
83+ libc, err := load.OpenLibrary(library)
9684 if err != nil {
9785 t.Fatalf("failed to dlopen: %s", err)
9886 }
@@ -123,10 +111,15 @@ func TestRegisterFunc_Floats(t *testing.T) {
123111 }
124112
125113 func TestRegisterLibFunc_Bool(t *testing.T) {
114+ if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
115+ t.Skip("Platform doesn't support callbacks")
116+ return
117+ }
126118 // this callback recreates the state where the return register
127119 // contains other information but the least significant byte is false
128120 cbFalse := purego.NewCallback(func() uintptr {
129- return 0x7F5948AE9A00
121+ x := uint64(0x7F5948AE9A00)
122+ return uintptr(x)
130123 })
131124 var runFalse func() bool
132125 purego.RegisterFunc(&runFalse, cbFalse)
@@ -10,13 +10,9 @@ import (
10 "unsafe"10 "unsafe"
11 11
12 "github.com/ebitengine/purego"12 "github.com/ebitengine/purego"
13+ "github.com/ebitengine/purego/internal/load"
13 )14 )
14 15
15-// This is an internal OS-dependent function for getting the handle to a library
16-//
17-//go:linkname openLibrary openLibrary
18-func openLibrary(name string) (uintptr, error)
19-
20 func getSystemLibrary() (string, error) {16 func getSystemLibrary() (string, error) {
21 switch runtime.GOOS {17 switch runtime.GOOS {
22 case "darwin":18 case "darwin":
@@ -37,7 +33,7 @@ func TestRegisterFunc(t *testing.T) {
37 if err != nil {33 if err != nil {
38 t.Fatalf("couldn't get system library: %s", err)34 t.Fatalf("couldn't get system library: %s", err)
39 }35 }
40- libc, err := openLibrary(library)36+ libc, err := load.OpenLibrary(library)
41 if err != nil {37 if err != nil {
42 t.Fatalf("failed to dlopen: %s", err)38 t.Fatalf("failed to dlopen: %s", err)
43 }39 }
@@ -46,38 +42,26 @@ func TestRegisterFunc(t *testing.T) {
46 puts("Calling C from from Go without Cgo!")42 puts("Calling C from from Go without Cgo!")
47 }43 }
48 44
49-func ExampleNewCallback() {
50- cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int {
51- fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
52- return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15
53- })
54-
55- var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 int) int
56- purego.RegisterFunc(&fn, cb)
57-
58- ret := fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
59- fmt.Println(ret)
60-
61- // Output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
62- // 120
63-}
64-
65 func Test_qsort(t *testing.T) {45 func Test_qsort(t *testing.T) {
46+ if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
47+ t.Skip("Platform doesn't support Floats")
48+ return
49+ }
66 library, err := getSystemLibrary()50 library, err := getSystemLibrary()
67 if err != nil {51 if err != nil {
68 t.Fatalf("couldn't get system library: %s", err)52 t.Fatalf("couldn't get system library: %s", err)
69 }53 }
70- libc, err := openLibrary(library)54+ libc, err := load.OpenLibrary(library)
71 if err != nil {55 if err != nil {
72 t.Fatalf("failed to dlopen: %s", err)56 t.Fatalf("failed to dlopen: %s", err)
73 }57 }
74 58
75 data := []int{88, 56, 100, 2, 25}59 data := []int{88, 56, 100, 2, 25}
76 sorted := []int{2, 25, 56, 88, 100}60 sorted := []int{2, 25, 56, 88, 100}
77- compare := func(a, b *int) int {61+ compare := func(_ purego.CDecl, a, b *int) int {
78 return *a - *b62 return *a - *b
79 }63 }
80- var qsort func(data []int, nitms uintptr, size uintptr, compar func(a, b *int) int)64+ var qsort func(data []int, nitms uintptr, size uintptr, compar func(_ purego.CDecl, a, b *int) int)
81 purego.RegisterLibFunc(&qsort, libc, "qsort")65 purego.RegisterLibFunc(&qsort, libc, "qsort")
82 qsort(data, uintptr(len(data)), unsafe.Sizeof(int(0)), compare)66 qsort(data, uintptr(len(data)), unsafe.Sizeof(int(0)), compare)
83 for i := range data {67 for i := range data {
@@ -88,11 +72,15 @@ func Test_qsort(t *testing.T) {
88 }72 }
89 73
90 func TestRegisterFunc_Floats(t *testing.T) {74 func TestRegisterFunc_Floats(t *testing.T) {
75+ if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
76+ t.Skip("Platform doesn't support Floats")
77+ return
78+ }
91 library, err := getSystemLibrary()79 library, err := getSystemLibrary()
92 if err != nil {80 if err != nil {
93 t.Fatalf("couldn't get system library: %s", err)81 t.Fatalf("couldn't get system library: %s", err)
94 }82 }
95- libc, err := openLibrary(library)83+ libc, err := load.OpenLibrary(library)
96 if err != nil {84 if err != nil {
97 t.Fatalf("failed to dlopen: %s", err)85 t.Fatalf("failed to dlopen: %s", err)
98 }86 }
@@ -123,10 +111,15 @@ func TestRegisterFunc_Floats(t *testing.T) {
123 }111 }
124 112
125 func TestRegisterLibFunc_Bool(t *testing.T) {113 func TestRegisterLibFunc_Bool(t *testing.T) {
114+ if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
115+ t.Skip("Platform doesn't support callbacks")
116+ return
117+ }
126 // this callback recreates the state where the return register118 // this callback recreates the state where the return register
127 // contains other information but the least significant byte is false119 // contains other information but the least significant byte is false
128 cbFalse := purego.NewCallback(func() uintptr {120 cbFalse := purego.NewCallback(func() uintptr {
129- return 0x7F5948AE9A00121+ x := uint64(0x7F5948AE9A00)
122+ return uintptr(x)
130 })123 })
131 var runFalse func() bool124 var runFalse func() bool
132 purego.RegisterFunc(&runFalse, cbFalse)125 purego.RegisterFunc(&runFalse, cbFalse)
M internal/cgo/syscall_cgo_unix.go +4 -4
@@ -20,7 +20,7 @@ typedef struct syscall15Args {
2020 uintptr_t fn;
2121 uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
2222 uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
23- uintptr_t r1, r2, err;
23+ uintptr_t err;
2424 } syscall15Args;
2525
2626 void syscall15(struct syscall15Args *args) {
@@ -31,7 +31,7 @@ void syscall15(struct syscall15Args *args) {
3131 *(void**)(&func_name) = (void*)(args->fn);
3232 uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
3333 args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);
34- args->r1 = r1;
34+ args->a1 = r1;
3535 args->err = errno;
3636 }
3737
@@ -48,8 +48,8 @@ func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14,
4848 C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
4949 C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
5050 C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),
51- C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51+ C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0,
5252 }
5353 C.syscall15(&args)
54- return uintptr(args.r1), uintptr(args.r2), uintptr(args.err)
54+ return uintptr(args.a1), 0, uintptr(args.err)
5555 }
@@ -20,7 +20,7 @@ typedef struct syscall15Args {
20 uintptr_t fn;20 uintptr_t fn;
21 uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;21 uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
22 uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;22 uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
23- uintptr_t r1, r2, err;23+ uintptr_t err;
24 } syscall15Args;24 } syscall15Args;
25 25
26 void syscall15(struct syscall15Args *args) {26 void syscall15(struct syscall15Args *args) {
@@ -31,7 +31,7 @@ void syscall15(struct syscall15Args *args) {
31 *(void**)(&func_name) = (void*)(args->fn);31 *(void**)(&func_name) = (void*)(args->fn);
32 uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,32 uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
33 args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);33 args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);
34- args->r1 = r1;34+ args->a1 = r1;
35 args->err = errno;35 args->err = errno;
36 }36 }
37 37
@@ -48,8 +48,8 @@ func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14,
48 C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),48 C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
49 C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),49 C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
50 C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),50 C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),
51- C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,51+ C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 }52 }
53 C.syscall15(&args)53 C.syscall15(&args)
54- return uintptr(args.r1), uintptr(args.r2), uintptr(args.err)54+ return uintptr(args.a1), 0, uintptr(args.err)
55 }55 }
M internal/fakecgo/callbacks.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin || freebsd || linux
5+//go:build !cgo && (darwin || freebsd || linux)
66
77 package fakecgo
88
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin || freebsd || linux5+//go:build !cgo && (darwin || freebsd || linux)
6 6
7 package fakecgo7 package fakecgo
8 8
M internal/fakecgo/doc.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || freebsd || linux
4+//go:build !cgo && (darwin || freebsd || linux)
55
66 // Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.
77 // This allows code that calls into C to function properly when CGO_ENABLED=0.
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || freebsd || linux4+//go:build !cgo && (darwin || freebsd || linux)
5 5
6 // Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.6 // Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.
7 // This allows code that calls into C to function properly when CGO_ENABLED=0.7 // This allows code that calls into C to function properly when CGO_ENABLED=0.
M internal/fakecgo/gen.go +4 -2
@@ -20,7 +20,7 @@ const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT
2020 // SPDX-License-Identifier: Apache-2.0
2121 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
2222
23-//go:build darwin || freebsd || linux
23+//go:build !cgo && (darwin || freebsd || linux)
2424
2525 package fakecgo
2626
@@ -88,7 +88,7 @@ const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go
8888 // SPDX-License-Identifier: Apache-2.0
8989 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
9090
91-//go:build darwin || freebsd || linux
91+//go:build !cgo && (darwin || freebsd || linux)
9292
9393 #include "textflag.h"
9494
@@ -105,6 +105,8 @@ const templateSymbolsGoos = `// Code generated by 'go generate' with gen.go. DO
105105 // SPDX-License-Identifier: Apache-2.0
106106 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
107107
108+//go:build !cgo
109+
108110 package fakecgo
109111
110112 {{- range $location := . }}
@@ -20,7 +20,7 @@ const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT
20 // SPDX-License-Identifier: Apache-2.020 // SPDX-License-Identifier: Apache-2.0
21 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors21 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
22 22
23-//go:build darwin || freebsd || linux23+//go:build !cgo && (darwin || freebsd || linux)
24 24
25 package fakecgo25 package fakecgo
26 26
@@ -88,7 +88,7 @@ const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go
88 // SPDX-License-Identifier: Apache-2.088 // SPDX-License-Identifier: Apache-2.0
89 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors89 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
90 90
91-//go:build darwin || freebsd || linux91+//go:build !cgo && (darwin || freebsd || linux)
92 92
93 #include "textflag.h"93 #include "textflag.h"
94 94
@@ -105,6 +105,8 @@ const templateSymbolsGoos = `// Code generated by 'go generate' with gen.go. DO
105 // SPDX-License-Identifier: Apache-2.0105 // SPDX-License-Identifier: Apache-2.0
106 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors106 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
107 107
108+//go:build !cgo
109+
108 package fakecgo110 package fakecgo
109 111
110 {{- range $location := . }}112 {{- range $location := . }}
M internal/fakecgo/go_darwin_amd64.go +2 -0
@@ -2,6 +2,8 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5+//go:build !cgo
6+
57 package fakecgo
68
79 import "unsafe"
@@ -2,6 +2,8 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5+//go:build !cgo
6+
5 package fakecgo7 package fakecgo
6 8
7 import "unsafe"9 import "unsafe"
M internal/fakecgo/go_darwin_arm64.go +2 -0
@@ -2,6 +2,8 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5+//go:build !cgo
6+
57 package fakecgo
68
79 import "unsafe"
@@ -2,6 +2,8 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5+//go:build !cgo
6+
5 package fakecgo7 package fakecgo
6 8
7 import "unsafe"9 import "unsafe"
M internal/fakecgo/go_freebsd_amd64.go +2 -0
@@ -2,6 +2,8 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5+//go:build !cgo
6+
57 package fakecgo
68
79 import "unsafe"
@@ -2,6 +2,8 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5+//go:build !cgo
6+
5 package fakecgo7 package fakecgo
6 8
7 import "unsafe"9 import "unsafe"
M internal/fakecgo/go_freebsd_arm64.go +3 -1
@@ -2,6 +2,8 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5+//go:build !cgo
6+
57 package fakecgo
68
79 import "unsafe"
@@ -14,7 +16,7 @@ func _cgo_sys_thread_start(ts *ThreadStart) {
1416 var size size_t
1517 var err int
1618
17- //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
19+ // fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
1820 sigfillset(&ign)
1921 pthread_sigmask(SIG_SETMASK, &ign, &oset)
2022
@@ -2,6 +2,8 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5+//go:build !cgo
6+
5 package fakecgo7 package fakecgo
6 8
7 import "unsafe"9 import "unsafe"
@@ -14,7 +16,7 @@ func _cgo_sys_thread_start(ts *ThreadStart) {
14 var size size_t16 var size size_t
15 var err int17 var err int
16 18
17- //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug19+ // fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
18 sigfillset(&ign)20 sigfillset(&ign)
19 pthread_sigmask(SIG_SETMASK, &ign, &oset)21 pthread_sigmask(SIG_SETMASK, &ign, &oset)
20 22
M internal/fakecgo/go_libinit.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || freebsd || linux
4+//go:build !cgo && (darwin || freebsd || linux)
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || freebsd || linux4+//go:build !cgo && (darwin || freebsd || linux)
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/go_linux_amd64.go +2 -0
@@ -2,6 +2,8 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5+//go:build !cgo
6+
57 package fakecgo
68
79 import "unsafe"
@@ -2,6 +2,8 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5+//go:build !cgo
6+
5 package fakecgo7 package fakecgo
6 8
7 import "unsafe"9 import "unsafe"
M internal/fakecgo/go_linux_arm64.go +2 -0
@@ -2,6 +2,8 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5+//go:build !cgo
6+
57 package fakecgo
68
79 import "unsafe"
@@ -2,6 +2,8 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5+//go:build !cgo
6+
5 package fakecgo7 package fakecgo
6 8
7 import "unsafe"9 import "unsafe"
M internal/fakecgo/go_setenv.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || freebsd || linux
4+//go:build !cgo && (darwin || freebsd || linux)
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || freebsd || linux4+//go:build !cgo && (darwin || freebsd || linux)
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/go_util.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || freebsd || linux
4+//go:build !cgo && (darwin || freebsd || linux)
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || freebsd || linux4+//go:build !cgo && (darwin || freebsd || linux)
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/iscgo.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin || freebsd || linux
5+//go:build !cgo && (darwin || freebsd || linux)
66
77 // The runtime package contains an uninitialized definition
88 // for runtime·iscgo. Override it to tell the runtime we're here.
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin || freebsd || linux5+//go:build !cgo && (darwin || freebsd || linux)
6 6
7 // The runtime package contains an uninitialized definition7 // The runtime package contains an uninitialized definition
8 // for runtime·iscgo. Override it to tell the runtime we're here.8 // for runtime·iscgo. Override it to tell the runtime we're here.
M internal/fakecgo/libcgo.go +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || freebsd || linux
4+//go:build !cgo && (darwin || freebsd || linux)
55
66 package fakecgo
77
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || freebsd || linux4+//go:build !cgo && (darwin || freebsd || linux)
5 5
6 package fakecgo6 package fakecgo
7 7
M internal/fakecgo/libcgo_darwin.go +2 -0
@@ -1,6 +1,8 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4+//go:build !cgo
5+
46 package fakecgo
57
68 type (
@@ -1,6 +1,8 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4+//go:build !cgo
5+
4 package fakecgo6 package fakecgo
5 7
6 type (8 type (
M internal/fakecgo/libcgo_freebsd.go +2 -0
@@ -1,6 +1,8 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4+//go:build !cgo
5+
46 package fakecgo
57
68 type (
@@ -1,6 +1,8 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4+//go:build !cgo
5+
4 package fakecgo6 package fakecgo
5 7
6 type (8 type (
M internal/fakecgo/libcgo_linux.go +2 -0
@@ -1,6 +1,8 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4+//go:build !cgo
5+
46 package fakecgo
57
68 type (
@@ -1,6 +1,8 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4+//go:build !cgo
5+
4 package fakecgo6 package fakecgo
5 7
6 type (8 type (
M internal/fakecgo/setenv.go +1 -1
@@ -2,7 +2,7 @@
22 // Use of this source code is governed by a BSD-style
33 // license that can be found in the LICENSE file.
44
5-//go:build darwin || freebsd || linux
5+//go:build !cgo && (darwin || freebsd || linux)
66
77 package fakecgo
88
@@ -2,7 +2,7 @@
2 // Use of this source code is governed by a BSD-style2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.3 // license that can be found in the LICENSE file.
4 4
5-//go:build darwin || freebsd || linux5+//go:build !cgo && (darwin || freebsd || linux)
6 6
7 package fakecgo7 package fakecgo
8 8
M internal/fakecgo/symbols.go +1 -1
@@ -3,7 +3,7 @@
33 // SPDX-License-Identifier: Apache-2.0
44 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
55
6-//go:build darwin || freebsd || linux
6+//go:build !cgo && (darwin || freebsd || linux)
77
88 package fakecgo
99
@@ -3,7 +3,7 @@
3 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5 5
6-//go:build darwin || freebsd || linux6+//go:build !cgo && (darwin || freebsd || linux)
7 7
8 package fakecgo8 package fakecgo
9 9
M internal/fakecgo/symbols_darwin.go +2 -0
@@ -3,6 +3,8 @@
33 // SPDX-License-Identifier: Apache-2.0
44 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
55
6+//go:build !cgo
7+
68 package fakecgo
79
810 //go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"
@@ -3,6 +3,8 @@
3 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5 5
6+//go:build !cgo
7+
6 package fakecgo8 package fakecgo
7 9
8 //go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"10 //go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"
M internal/fakecgo/symbols_freebsd.go +2 -0
@@ -3,6 +3,8 @@
33 // SPDX-License-Identifier: Apache-2.0
44 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
55
6+//go:build !cgo
7+
68 package fakecgo
79
810 //go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
@@ -3,6 +3,8 @@
3 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5 5
6+//go:build !cgo
7+
6 package fakecgo8 package fakecgo
7 9
8 //go:cgo_import_dynamic purego_malloc malloc "libc.so.7"10 //go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
M internal/fakecgo/symbols_linux.go +2 -0
@@ -3,6 +3,8 @@
33 // SPDX-License-Identifier: Apache-2.0
44 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
55
6+//go:build !cgo
7+
68 package fakecgo
79
810 //go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
@@ -3,6 +3,8 @@
3 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5 5
6+//go:build !cgo
7+
6 package fakecgo8 package fakecgo
7 9
8 //go:cgo_import_dynamic purego_malloc malloc "libc.so.6"10 //go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
M internal/fakecgo/trampolines_amd64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || linux || freebsd
4+//go:build !cgo && (darwin || linux || freebsd)
55
66 /*
77 trampoline for emulating required C functions for cgo in go (see cgo.go)
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || linux || freebsd4+//go:build !cgo && (darwin || linux || freebsd)
5 5
6 /*6 /*
7 trampoline for emulating required C functions for cgo in go (see cgo.go)7 trampoline for emulating required C functions for cgo in go (see cgo.go)
M internal/fakecgo/trampolines_arm64.s +1 -1
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build darwin || freebsd || linux
4+//go:build !cgo && (darwin || freebsd || linux)
55
66 #include "textflag.h"
77 #include "go_asm.h"
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build darwin || freebsd || linux4+//go:build !cgo && (darwin || freebsd || linux)
5 5
6 #include "textflag.h"6 #include "textflag.h"
7 #include "go_asm.h"7 #include "go_asm.h"
M internal/fakecgo/trampolines_stubs.s +1 -1
@@ -3,7 +3,7 @@
33 // SPDX-License-Identifier: Apache-2.0
44 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
55
6-//go:build darwin || freebsd || linux
6+//go:build !cgo && (darwin || freebsd || linux)
77
88 #include "textflag.h"
99
@@ -3,7 +3,7 @@
3 // SPDX-License-Identifier: Apache-2.03 // SPDX-License-Identifier: Apache-2.0
4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors4 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5 5
6-//go:build darwin || freebsd || linux6+//go:build !cgo && (darwin || freebsd || linux)
7 7
8 #include "textflag.h"8 #include "textflag.h"
9 9
A internal/load/load_unix.go +16 -0
@@ -0,0 +1,16 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
3+
4+//go:build darwin || freebsd || linux
5+
6+package load
7+
8+import "github.com/ebitengine/purego"
9+
10+func OpenLibrary(name string) (uintptr, error) {
11+ return purego.Dlopen(name, purego.RTLD_NOW|purego.RTLD_GLOBAL)
12+}
13+
14+func OpenSymbol(lib uintptr, name string) (uintptr, error) {
15+ return purego.Dlsym(lib, name)
16+}
@@ -0,0 +1,16 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
3+
4+//go:build darwin || freebsd || linux
5+
6+package load
7+
8+import "github.com/ebitengine/purego"
9+
10+func OpenLibrary(name string) (uintptr, error) {
11+ return purego.Dlopen(name, purego.RTLD_NOW|purego.RTLD_GLOBAL)
12+}
13+
14+func OpenSymbol(lib uintptr, name string) (uintptr, error) {
15+ return purego.Dlsym(lib, name)
16+}
A internal/load/load_windows.go +15 -0
@@ -0,0 +1,15 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
3+
4+package load
5+
6+import "golang.org/x/sys/windows"
7+
8+func OpenLibrary(name string) (uintptr, error) {
9+ handle, err := windows.LoadLibrary(name)
10+ return uintptr(handle), err
11+}
12+
13+func OpenSymbol(lib uintptr, name string) (uintptr, error) {
14+ return windows.GetProcAddress(windows.Handle(lib), name)
15+}
@@ -0,0 +1,15 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
3+
4+package load
5+
6+import "golang.org/x/sys/windows"
7+
8+func OpenLibrary(name string) (uintptr, error) {
9+ handle, err := windows.LoadLibrary(name)
10+ return uintptr(handle), err
11+}
12+
13+func OpenSymbol(lib uintptr, name string) (uintptr, error) {
14+ return windows.GetProcAddress(windows.Handle(lib), name)
15+}
M syscall.go +7 -0
@@ -5,6 +5,13 @@
55
66 package purego
77
8+// CDecl marks a function as being called using the __cdecl calling convention as defined in
9+// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
10+// This is only useful on 386 Windows, but it is safe to use on other platforms.
11+//
12+// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
13+type CDecl struct{}
14+
815 const (
916 maxArgs = 15
1017 numOfFloats = 8 // arm64 and amd64 both have 8 float registers
@@ -5,6 +5,13 @@
5 5
6 package purego6 package purego
7 7
8+// CDecl marks a function as being called using the __cdecl calling convention as defined in
9+// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
10+// This is only useful on 386 Windows, but it is safe to use on other platforms.
11+//
12+// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
13+type CDecl struct{}
14+
8 const (15 const (
9 maxArgs = 1516 maxArgs = 15
10 numOfFloats = 8 // arm64 and amd64 both have 8 float registers17 numOfFloats = 8 // arm64 and amd64 both have 8 float registers
M syscall_cgo_linux.go +0 -2
@@ -6,8 +6,6 @@
66 package purego
77
88 import (
9- _ "unsafe" // for go:linkname
10-
119 "github.com/ebitengine/purego/internal/cgo"
1210 )
1311
@@ -6,8 +6,6 @@
6 package purego6 package purego
7 7
8 import (8 import (
9- _ "unsafe" // for go:linkname
10-
11 "github.com/ebitengine/purego/internal/cgo"9 "github.com/ebitengine/purego/internal/cgo"
12 )10 )
13 11
M syscall_sysv.go +21 -1
@@ -32,6 +32,16 @@ func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
3232 // for these callbacks is never released. At least 2000 callbacks can always be created. Although this function
3333 // provides similar functionality to windows.NewCallback it is distinct.
3434 func NewCallback(fn interface{}) uintptr {
35+ ty := reflect.TypeOf(fn)
36+ for i := 0; i < ty.NumIn(); i++ {
37+ in := ty.In(i)
38+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
39+ continue
40+ }
41+ if i != 0 {
42+ panic("purego: CDecl must be the first argument")
43+ }
44+ }
3545 return compileCallback(fn)
3646 }
3747
@@ -73,7 +83,12 @@ func compileCallback(fn interface{}) uintptr {
7383 for i := 0; i < ty.NumIn(); i++ {
7484 in := ty.In(i)
7585 switch in.Kind() {
76- case reflect.Struct, reflect.Interface, reflect.Func, reflect.Slice,
86+ case reflect.Struct:
87+ if i == 0 && in.AssignableTo(reflect.TypeOf(CDecl{})) {
88+ continue
89+ }
90+ fallthrough
91+ case reflect.Interface, reflect.Func, reflect.Slice,
7792 reflect.Chan, reflect.Complex64, reflect.Complex128,
7893 reflect.String, reflect.Map, reflect.Invalid:
7994 panic("purego: unsupported argument type: " + in.Kind().String())
@@ -143,7 +158,12 @@ func callbackWrap(a *callbackArgs) {
143158 pos = floatsN
144159 }
145160 floatsN++
161+ case reflect.Struct:
162+ // This is the CDecl field
163+ args[i] = reflect.Zero(fnType.In(i))
164+ continue
146165 default:
166+
147167 if intsN >= numOfIntegerRegisters() {
148168 pos = stack
149169 stack++
@@ -32,6 +32,16 @@ func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
32 // for these callbacks is never released. At least 2000 callbacks can always be created. Although this function32 // for these callbacks is never released. At least 2000 callbacks can always be created. Although this function
33 // provides similar functionality to windows.NewCallback it is distinct.33 // provides similar functionality to windows.NewCallback it is distinct.
34 func NewCallback(fn interface{}) uintptr {34 func NewCallback(fn interface{}) uintptr {
35+ ty := reflect.TypeOf(fn)
36+ for i := 0; i < ty.NumIn(); i++ {
37+ in := ty.In(i)
38+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
39+ continue
40+ }
41+ if i != 0 {
42+ panic("purego: CDecl must be the first argument")
43+ }
44+ }
35 return compileCallback(fn)45 return compileCallback(fn)
36 }46 }
37 47
@@ -73,7 +83,12 @@ func compileCallback(fn interface{}) uintptr {
73 for i := 0; i < ty.NumIn(); i++ {83 for i := 0; i < ty.NumIn(); i++ {
74 in := ty.In(i)84 in := ty.In(i)
75 switch in.Kind() {85 switch in.Kind() {
76- case reflect.Struct, reflect.Interface, reflect.Func, reflect.Slice,86+ case reflect.Struct:
87+ if i == 0 && in.AssignableTo(reflect.TypeOf(CDecl{})) {
88+ continue
89+ }
90+ fallthrough
91+ case reflect.Interface, reflect.Func, reflect.Slice,
77 reflect.Chan, reflect.Complex64, reflect.Complex128,92 reflect.Chan, reflect.Complex64, reflect.Complex128,
78 reflect.String, reflect.Map, reflect.Invalid:93 reflect.String, reflect.Map, reflect.Invalid:
79 panic("purego: unsupported argument type: " + in.Kind().String())94 panic("purego: unsupported argument type: " + in.Kind().String())
@@ -143,7 +158,12 @@ func callbackWrap(a *callbackArgs) {
143 pos = floatsN158 pos = floatsN
144 }159 }
145 floatsN++160 floatsN++
161+ case reflect.Struct:
162+ // This is the CDecl field
163+ args[i] = reflect.Zero(fnType.In(i))
164+ continue
146 default:165 default:
166+
147 if intsN >= numOfIntegerRegisters() {167 if intsN >= numOfIntegerRegisters() {
148 pos = stack168 pos = stack
149 stack++169 stack++
M syscall_windows.go +16 -7
@@ -4,8 +4,8 @@
44 package purego
55
66 import (
7+ "reflect"
78 "syscall"
8- _ "unsafe" // only for go:linkname
99
1010 "golang.org/x/sys/windows"
1111 )
@@ -25,15 +25,24 @@ func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
2525 // callbacks can always be created. Although this function is similiar to the darwin version it may act
2626 // differently.
2727 func NewCallback(fn interface{}) uintptr {
28+ isCDecl := false
29+ ty := reflect.TypeOf(fn)
30+ for i := 0; i < ty.NumIn(); i++ {
31+ in := ty.In(i)
32+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
33+ continue
34+ }
35+ if i != 0 {
36+ panic("purego: CDecl must be the first argument")
37+ }
38+ isCDecl = true
39+ }
40+ if isCDecl {
41+ return syscall.NewCallbackCDecl(fn)
42+ }
2843 return syscall.NewCallback(fn)
2944 }
3045
31-//go:linkname openLibrary openLibrary
32-func openLibrary(name string) (uintptr, error) {
33- handle, err := windows.LoadLibrary(name)
34- return uintptr(handle), err
35-}
36-
3746 func loadSymbol(handle uintptr, name string) (uintptr, error) {
3847 return windows.GetProcAddress(windows.Handle(handle), name)
3948 }
@@ -4,8 +4,8 @@
4 package purego4 package purego
5 5
6 import (6 import (
7+ "reflect"
7 "syscall"8 "syscall"
8- _ "unsafe" // only for go:linkname
9 9
10 "golang.org/x/sys/windows"10 "golang.org/x/sys/windows"
11 )11 )
@@ -25,15 +25,24 @@ func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a
25 // callbacks can always be created. Although this function is similiar to the darwin version it may act25 // callbacks can always be created. Although this function is similiar to the darwin version it may act
26 // differently.26 // differently.
27 func NewCallback(fn interface{}) uintptr {27 func NewCallback(fn interface{}) uintptr {
28+ isCDecl := false
29+ ty := reflect.TypeOf(fn)
30+ for i := 0; i < ty.NumIn(); i++ {
31+ in := ty.In(i)
32+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
33+ continue
34+ }
35+ if i != 0 {
36+ panic("purego: CDecl must be the first argument")
37+ }
38+ isCDecl = true
39+ }
40+ if isCDecl {
41+ return syscall.NewCallbackCDecl(fn)
42+ }
28 return syscall.NewCallback(fn)43 return syscall.NewCallback(fn)
29 }44 }
30 45
31-//go:linkname openLibrary openLibrary
32-func openLibrary(name string) (uintptr, error) {
33- handle, err := windows.LoadLibrary(name)
34- return uintptr(handle), err
35-}
36-
37 func loadSymbol(handle uintptr, name string) (uintptr, error) {46 func loadSymbol(handle uintptr, name string) (uintptr, error) {
38 return windows.GetProcAddress(windows.Handle(handle), name)47 return windows.GetProcAddress(windows.Handle(handle), name)
39 }48 }

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