github.com/ebitengine/purego@v0.8.0-alpha.2.0.20240512170805-6cd12240d332/func_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors 3 4 package purego_test 5 6 import ( 7 "fmt" 8 "runtime" 9 "testing" 10 "unsafe" 11 12 "github.com/ebitengine/purego" 13 "github.com/ebitengine/purego/internal/load" 14 ) 15 16 func getSystemLibrary() (string, error) { 17 switch runtime.GOOS { 18 case "darwin": 19 return "/usr/lib/libSystem.B.dylib", nil 20 case "linux": 21 return "libc.so.6", nil 22 case "freebsd": 23 return "libc.so.7", nil 24 case "windows": 25 return "ucrtbase.dll", nil 26 default: 27 return "", fmt.Errorf("GOOS=%s is not supported", runtime.GOOS) 28 } 29 } 30 31 func TestRegisterFunc(t *testing.T) { 32 library, err := getSystemLibrary() 33 if err != nil { 34 t.Fatalf("couldn't get system library: %s", err) 35 } 36 libc, err := load.OpenLibrary(library) 37 if err != nil { 38 t.Fatalf("failed to dlopen: %s", err) 39 } 40 var puts func(string) 41 purego.RegisterLibFunc(&puts, libc, "puts") 42 puts("Calling C from from Go without Cgo!") 43 } 44 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 } 50 library, err := getSystemLibrary() 51 if err != nil { 52 t.Fatalf("couldn't get system library: %s", err) 53 } 54 libc, err := load.OpenLibrary(library) 55 if err != nil { 56 t.Fatalf("failed to dlopen: %s", err) 57 } 58 59 data := []int{88, 56, 100, 2, 25} 60 sorted := []int{2, 25, 56, 88, 100} 61 compare := func(_ purego.CDecl, a, b *int) int { 62 return *a - *b 63 } 64 var qsort func(data []int, nitms uintptr, size uintptr, compar func(_ purego.CDecl, a, b *int) int) 65 purego.RegisterLibFunc(&qsort, libc, "qsort") 66 qsort(data, uintptr(len(data)), unsafe.Sizeof(int(0)), compare) 67 for i := range data { 68 if data[i] != sorted[i] { 69 t.Errorf("got %d wanted %d at %d", data[i], sorted[i], i) 70 } 71 } 72 } 73 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 } 79 library, err := getSystemLibrary() 80 if err != nil { 81 t.Fatalf("couldn't get system library: %s", err) 82 } 83 libc, err := load.OpenLibrary(library) 84 if err != nil { 85 t.Fatalf("failed to dlopen: %s", err) 86 } 87 { 88 var strtof func(arg string) float32 89 purego.RegisterLibFunc(&strtof, libc, "strtof") 90 const ( 91 arg = "2" 92 ) 93 got := strtof(arg) 94 expected := float32(2) 95 if got != expected { 96 t.Errorf("strtof failed. got %f but wanted %f", got, expected) 97 } 98 } 99 { 100 var strtod func(arg string, ptr **byte) float64 101 purego.RegisterLibFunc(&strtod, libc, "strtod") 102 const ( 103 arg = "1" 104 ) 105 got := strtod(arg, nil) 106 expected := float64(1) 107 if got != expected { 108 t.Errorf("strtod failed. got %f but wanted %f", got, expected) 109 } 110 } 111 } 112 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 } 118 // this callback recreates the state where the return register 119 // contains other information but the least significant byte is false 120 cbFalse := purego.NewCallback(func() uintptr { 121 x := uint64(0x7F5948AE9A00) 122 return uintptr(x) 123 }) 124 var runFalse func() bool 125 purego.RegisterFunc(&runFalse, cbFalse) 126 expected := false 127 if got := runFalse(); got != expected { 128 t.Errorf("runFalse failed. got %t but wanted %t", got, expected) 129 } 130 }