purego: fix float returns (#177)
The bits for a float32 return value were being converted into a float64. This causes the returned value to be incorrect. This fix was to separate the float32 case and use math.Float32frombits. The test just makes sure that float32 and float64 return values are returned from C functions correctly.
- commit
- 2a2fe0f2bfbd84fa932e6af44c559f74eec9b600
- author
- TotallyGamerJet · · 2023-11-18 17:14 UTC
- committer
- Hajime Hoshi · · 2023-11-18 17:34 UTC
- parent
- e19c67f
- signature
- unsigned
2 files · +44 -5
M func.go +5 -1
| @@ -276,7 +276,11 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||
| 276 | 276 | RegisterFunc(v.Interface(), r1) | |
| 277 | 277 | case reflect.String: | |
| 278 | 278 | v.SetString(strings.GoString(r1)) | |
| 279 | - | case reflect.Float32, reflect.Float64: | |
| 279 | + | case reflect.Float32: | |
| 280 | + | // NOTE: r2 is only the floating return value on 64bit platforms. | |
| 281 | + | // On 32bit platforms r2 is the upper part of a 64bit return. | |
| 282 | + | v.SetFloat(float64(math.Float32frombits(uint32(r2)))) | |
| 283 | + | case reflect.Float64: | |
| 280 | 284 | // NOTE: r2 is only the floating return value on 64bit platforms. | |
| 281 | 285 | // On 32bit platforms r2 is the upper part of a 64bit return. | |
| 282 | 286 | v.SetFloat(math.Float64frombits(uint64(r2))) | |
| @@ -276,7 +276,11 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||||
| 276 | RegisterFunc(v.Interface(), r1) | 276 | RegisterFunc(v.Interface(), r1) | ||
| 277 | case reflect.String: | 277 | case reflect.String: | ||
| 278 | v.SetString(strings.GoString(r1)) | 278 | v.SetString(strings.GoString(r1)) | ||
| 279 | - | case reflect.Float32, reflect.Float64: | 279 | + | case reflect.Float32: |
| 280 | + | // NOTE: r2 is only the floating return value on 64bit platforms. | |||
| 281 | + | // On 32bit platforms r2 is the upper part of a 64bit return. | |||
| 282 | + | v.SetFloat(float64(math.Float32frombits(uint32(r2)))) | |||
| 283 | + | case reflect.Float64: | |||
| 280 | // NOTE: r2 is only the floating return value on 64bit platforms. | 284 | // NOTE: r2 is only the floating return value on 64bit platforms. | ||
| 281 | // On 32bit platforms r2 is the upper part of a 64bit return. | 285 | // On 32bit platforms r2 is the upper part of a 64bit return. | ||
| 282 | v.SetFloat(math.Float64frombits(uint64(r2))) | 286 | v.SetFloat(math.Float64frombits(uint64(r2))) | ||
M func_test.go +39 -4
| @@ -35,11 +35,11 @@ func getSystemLibrary() (string, error) { | |||
| 35 | 35 | func TestRegisterFunc(t *testing.T) { | |
| 36 | 36 | library, err := getSystemLibrary() | |
| 37 | 37 | if err != nil { | |
| 38 | - | t.Errorf("couldn't get system library: %s", err) | |
| 38 | + | t.Fatalf("couldn't get system library: %s", err) | |
| 39 | 39 | } | |
| 40 | 40 | libc, err := openLibrary(library) | |
| 41 | 41 | if err != nil { | |
| 42 | - | t.Errorf("failed to dlopen: %s", err) | |
| 42 | + | t.Fatalf("failed to dlopen: %s", err) | |
| 43 | 43 | } | |
| 44 | 44 | var puts func(string) | |
| 45 | 45 | purego.RegisterLibFunc(&puts, libc, "puts") | |
| @@ -76,11 +76,11 @@ func Test_qsort(t *testing.T) { | |||
| 76 | 76 | ||
| 77 | 77 | library, err := getSystemLibrary() | |
| 78 | 78 | if err != nil { | |
| 79 | - | t.Errorf("couldn't get system library: %s", err) | |
| 79 | + | t.Fatalf("couldn't get system library: %s", err) | |
| 80 | 80 | } | |
| 81 | 81 | libc, err := openLibrary(library) | |
| 82 | 82 | if err != nil { | |
| 83 | - | t.Errorf("failed to dlopen: %s", err) | |
| 83 | + | t.Fatalf("failed to dlopen: %s", err) | |
| 84 | 84 | } | |
| 85 | 85 | ||
| 86 | 86 | data := []int{88, 56, 100, 2, 25} | |
| @@ -97,3 +97,38 @@ func Test_qsort(t *testing.T) { | |||
| 97 | 97 | } | |
| 98 | 98 | } | |
| 99 | 99 | } | |
| 100 | + | ||
| 101 | + | func TestRegisterFunc_Floats(t *testing.T) { | |
| 102 | + | library, err := getSystemLibrary() | |
| 103 | + | if err != nil { | |
| 104 | + | t.Fatalf("couldn't get system library: %s", err) | |
| 105 | + | } | |
| 106 | + | libc, err := openLibrary(library) | |
| 107 | + | if err != nil { | |
| 108 | + | t.Fatalf("failed to dlopen: %s", err) | |
| 109 | + | } | |
| 110 | + | { | |
| 111 | + | var strtof func(arg string) float32 | |
| 112 | + | purego.RegisterLibFunc(&strtof, libc, "strtof") | |
| 113 | + | const ( | |
| 114 | + | arg = "2" | |
| 115 | + | ) | |
| 116 | + | got := strtof(arg) | |
| 117 | + | expected := float32(2) | |
| 118 | + | if got != expected { | |
| 119 | + | t.Errorf("strtof failed. got %f but wanted %f", got, expected) | |
| 120 | + | } | |
| 121 | + | } | |
| 122 | + | { | |
| 123 | + | var strtod func(arg string, ptr **byte) float64 | |
| 124 | + | purego.RegisterLibFunc(&strtod, libc, "strtod") | |
| 125 | + | const ( | |
| 126 | + | arg = "1" | |
| 127 | + | ) | |
| 128 | + | got := strtod(arg, nil) | |
| 129 | + | expected := float64(1) | |
| 130 | + | if got != expected { | |
| 131 | + | t.Errorf("strtod failed. got %f but wanted %f", got, expected) | |
| 132 | + | } | |
| 133 | + | } | |
| 134 | + | } | |
| @@ -35,11 +35,11 @@ func getSystemLibrary() (string, error) { | |||||
| 35 | func TestRegisterFunc(t *testing.T) { | 35 | func TestRegisterFunc(t *testing.T) { | ||
| 36 | library, err := getSystemLibrary() | 36 | library, err := getSystemLibrary() | ||
| 37 | if err != nil { | 37 | if err != nil { | ||
| 38 | - | t.Errorf("couldn't get system library: %s", err) | 38 | + | t.Fatalf("couldn't get system library: %s", err) |
| 39 | } | 39 | } | ||
| 40 | libc, err := openLibrary(library) | 40 | libc, err := openLibrary(library) | ||
| 41 | if err != nil { | 41 | if err != nil { | ||
| 42 | - | t.Errorf("failed to dlopen: %s", err) | 42 | + | t.Fatalf("failed to dlopen: %s", err) |
| 43 | } | 43 | } | ||
| 44 | var puts func(string) | 44 | var puts func(string) | ||
| 45 | purego.RegisterLibFunc(&puts, libc, "puts") | 45 | purego.RegisterLibFunc(&puts, libc, "puts") | ||
| @@ -76,11 +76,11 @@ func Test_qsort(t *testing.T) { | |||||
| 76 | 76 | ||||
| 77 | library, err := getSystemLibrary() | 77 | library, err := getSystemLibrary() | ||
| 78 | if err != nil { | 78 | if err != nil { | ||
| 79 | - | t.Errorf("couldn't get system library: %s", err) | 79 | + | t.Fatalf("couldn't get system library: %s", err) |
| 80 | } | 80 | } | ||
| 81 | libc, err := openLibrary(library) | 81 | libc, err := openLibrary(library) | ||
| 82 | if err != nil { | 82 | if err != nil { | ||
| 83 | - | t.Errorf("failed to dlopen: %s", err) | 83 | + | t.Fatalf("failed to dlopen: %s", err) |
| 84 | } | 84 | } | ||
| 85 | 85 | ||||
| 86 | data := []int{88, 56, 100, 2, 25} | 86 | data := []int{88, 56, 100, 2, 25} | ||
| @@ -97,3 +97,38 @@ func Test_qsort(t *testing.T) { | |||||
| 97 | } | 97 | } | ||
| 98 | } | 98 | } | ||
| 99 | } | 99 | } | ||
| 100 | + | ||||
| 101 | + | func TestRegisterFunc_Floats(t *testing.T) { | |||
| 102 | + | library, err := getSystemLibrary() | |||
| 103 | + | if err != nil { | |||
| 104 | + | t.Fatalf("couldn't get system library: %s", err) | |||
| 105 | + | } | |||
| 106 | + | libc, err := openLibrary(library) | |||
| 107 | + | if err != nil { | |||
| 108 | + | t.Fatalf("failed to dlopen: %s", err) | |||
| 109 | + | } | |||
| 110 | + | { | |||
| 111 | + | var strtof func(arg string) float32 | |||
| 112 | + | purego.RegisterLibFunc(&strtof, libc, "strtof") | |||
| 113 | + | const ( | |||
| 114 | + | arg = "2" | |||
| 115 | + | ) | |||
| 116 | + | got := strtof(arg) | |||
| 117 | + | expected := float32(2) | |||
| 118 | + | if got != expected { | |||
| 119 | + | t.Errorf("strtof failed. got %f but wanted %f", got, expected) | |||
| 120 | + | } | |||
| 121 | + | } | |||
| 122 | + | { | |||
| 123 | + | var strtod func(arg string, ptr **byte) float64 | |||
| 124 | + | purego.RegisterLibFunc(&strtod, libc, "strtod") | |||
| 125 | + | const ( | |||
| 126 | + | arg = "1" | |||
| 127 | + | ) | |||
| 128 | + | got := strtod(arg, nil) | |||
| 129 | + | expected := float64(1) | |||
| 130 | + | if got != expected { | |||
| 131 | + | t.Errorf("strtod failed. got %f but wanted %f", got, expected) | |||
| 132 | + | } | |||
| 133 | + | } | |||
| 134 | + | } | |||