forked from ebitengine/purego
-
Notifications
You must be signed in to change notification settings - Fork 1
/
func_test.go
143 lines (131 loc) · 3.46 KB
/
func_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
package purego_test
import (
"fmt"
"runtime"
"testing"
"unsafe"
"github.com/jwijenbergh/purego"
"github.com/jwijenbergh/purego/internal/load"
)
func getSystemLibrary() (string, error) {
switch runtime.GOOS {
case "darwin":
return "/usr/lib/libSystem.B.dylib", nil
case "linux":
return "libc.so.6", nil
case "freebsd":
return "libc.so.7", nil
case "windows":
return "ucrtbase.dll", nil
default:
return "", fmt.Errorf("GOOS=%s is not supported", runtime.GOOS)
}
}
func TestRegisterFunc(t *testing.T) {
library, err := getSystemLibrary()
if err != nil {
t.Fatalf("couldn't get system library: %s", err)
}
libc, err := load.OpenLibrary(library)
if err != nil {
t.Fatalf("failed to dlopen: %s", err)
}
var puts func(string)
purego.RegisterLibFunc(&puts, libc, "puts")
puts("Calling C from from Go without Cgo!")
}
func Test_qsort(t *testing.T) {
if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
t.Skip("Platform doesn't support Floats")
return
}
library, err := getSystemLibrary()
if err != nil {
t.Fatalf("couldn't get system library: %s", err)
}
libc, err := load.OpenLibrary(library)
if err != nil {
t.Fatalf("failed to dlopen: %s", err)
}
data := []int{88, 56, 100, 2, 25}
sorted := []int{2, 25, 56, 88, 100}
compare := func(_ purego.CDecl, a, b *int) int {
return *a - *b
}
var qsort func(data []int, nitms uintptr, size uintptr, compar func(_ purego.CDecl, a, b *int) int)
purego.RegisterLibFunc(&qsort, libc, "qsort")
qsort(data, uintptr(len(data)), unsafe.Sizeof(int(0)), compare)
for i := range data {
if data[i] != sorted[i] {
t.Errorf("got %d wanted %d at %d", data[i], sorted[i], i)
}
}
}
func TestRegisterFunc_Floats(t *testing.T) {
if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
t.Skip("Platform doesn't support Floats")
return
}
library, err := getSystemLibrary()
if err != nil {
t.Fatalf("couldn't get system library: %s", err)
}
libc, err := load.OpenLibrary(library)
if err != nil {
t.Fatalf("failed to dlopen: %s", err)
}
{
var strtof func(arg string) float32
purego.RegisterLibFunc(&strtof, libc, "strtof")
const (
arg = "2"
)
got := strtof(arg)
expected := float32(2)
if got != expected {
t.Errorf("strtof failed. got %f but wanted %f", got, expected)
}
}
{
var strtod func(arg string, ptr **byte) float64
purego.RegisterLibFunc(&strtod, libc, "strtod")
const (
arg = "1"
)
got := strtod(arg, nil)
expected := float64(1)
if got != expected {
t.Errorf("strtod failed. got %f but wanted %f", got, expected)
}
}
}
func TestRegisterLibFunc_Bool(t *testing.T) {
if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
t.Skip("Platform doesn't support callbacks")
return
}
// this callback recreates the state where the return register
// contains other information but the least significant byte is false
cbFalse := purego.NewCallback(func() uintptr {
x := uint64(0x7F5948AE9A00)
return uintptr(x)
})
var runFalse func() bool
purego.RegisterFunc(&runFalse, cbFalse)
expected := false
if got := runFalse(); got != expected {
t.Errorf("runFalse failed. got %t but wanted %t", got, expected)
}
}
func TestCallbackFnPtrDedup(t *testing.T) {
imp := func() uintptr {
return 0
}
ref1 := purego.NewCallbackFnPtr(&imp)
ref2 := purego.NewCallbackFnPtr(&imp)
if ref1 != ref2 {
t.Errorf("deduplicate expected %d to equal %d", ref1, ref2)
}
}