1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
3
4//go:build darwin && (arm64 || amd64)
5
6package purego_test
7
8import (
9 "os"
10 "path/filepath"
11 "runtime"
12 "testing"
13 "unsafe"
14
15 "github.com/ebitengine/purego"
16)
17
18func TestRegisterFunc_structArgs(t *testing.T) {
19 libFileName := filepath.Join(t.TempDir(), "structtest.so")
20 t.Logf("Build %v", libFileName)
21
22 if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "structtest", "struct_test.c")); err != nil {
23 t.Fatal(err)
24 }
25 defer os.Remove(libFileName)
26
27 lib, err := purego.Dlopen(libFileName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
28 if err != nil {
29 t.Fatalf("Dlopen(%q) failed: %v", libFileName, err)
30 }
31
32 const (
33 expectedUnsigned = 0xdeadbeef
34 expectedSigned = -123
35 expectedOdd = 12 + 23 + 46
36 expectedLong uint64 = 0xdeadbeefcafebabe
37 expectedFloat float32 = 10
38 expectedDouble float64 = 10
39 )
40
41 {
42 type Empty struct{}
43 var NoStruct func(Empty) int64
44 purego.RegisterLibFunc(&NoStruct, lib, "NoStruct")
45 if ret := NoStruct(Empty{}); ret != expectedUnsigned {
46 t.Fatalf("NoStruct returned %#x wanted %#x", ret, expectedUnsigned)
47 }
48 }
49 {
50 type EmptyEmpty struct{}
51 var EmptyEmptyFn func(EmptyEmpty) int64
52 purego.RegisterLibFunc(&EmptyEmptyFn, lib, "EmptyEmpty")
53 if ret := EmptyEmptyFn(EmptyEmpty{}); ret != expectedUnsigned {
54 t.Fatalf("EmptyEmpty returned %#x wanted %#x", ret, expectedUnsigned)
55 }
56 var EmptyEmptyWithReg func(uint32, EmptyEmpty, uint32) int64
57 purego.RegisterLibFunc(&EmptyEmptyWithReg, lib, "EmptyEmptyWithReg")
58 if ret := EmptyEmptyWithReg(0xdead, EmptyEmpty{}, 0xbeef); ret != expectedUnsigned {
59 t.Fatalf("EmptyEmptyWithReg returned %#x wanted %#x", ret, expectedUnsigned)
60 }
61 }
62 {
63 type GreaterThan16Bytes struct {
64 x, y, z *int64
65 }
66 var x, y, z int64 = 0xEF, 0xBE00, 0xDEAD0000
67 var GreaterThan16BytesFn func(GreaterThan16Bytes) int64
68 purego.RegisterLibFunc(&GreaterThan16BytesFn, lib, "GreaterThan16Bytes")
69 if ret := GreaterThan16BytesFn(GreaterThan16Bytes{x: &x, y: &y, z: &z}); ret != expectedUnsigned {
70 t.Fatalf("GreaterThan16Bytes returned %#x wanted %#x", ret, expectedUnsigned)
71 }
72 }
73 {
74 type GreaterThan16BytesStruct struct {
75 a struct {
76 x, y, z *int64
77 }
78 }
79 var x, y, z int64 = 0xEF, 0xBE00, 0xDEAD0000
80 var GreaterThan16BytesStructFn func(GreaterThan16BytesStruct) int64
81 purego.RegisterLibFunc(&GreaterThan16BytesStructFn, lib, "GreaterThan16BytesStruct")
82 if ret := GreaterThan16BytesStructFn(GreaterThan16BytesStruct{a: struct{ x, y, z *int64 }{x: &x, y: &y, z: &z}}); ret != expectedUnsigned {
83 t.Fatalf("GreaterThan16BytesStructFn returned %#x wanted %#x", ret, expectedUnsigned)
84 }
85 }
86 {
87 type GreaterThan16Bytes struct {
88 x, y, z *int64
89 }
90 var x, y, z int64 = 0xEF, 0xBE00, 0xDEAD0000
91 var AfterRegisters func(a, b, c, d, e, f, g, h int, bytes GreaterThan16Bytes) int64
92 purego.RegisterLibFunc(&AfterRegisters, lib, "AfterRegisters")
93 if ret := AfterRegisters(0xD0000000, 0xE000000, 0xA00000, 0xD0000, 0xB000, 0xE00, 0xE0, 0xF, GreaterThan16Bytes{x: &x, y: &y, z: &z}); ret != expectedUnsigned {
94 t.Fatalf("AfterRegisters returned %#x wanted %#x", ret, expectedUnsigned)
95 }
96 var BeforeRegisters func(bytes GreaterThan16Bytes, a, b int64) uint64
97 z -= 0xFF
98 purego.RegisterLibFunc(&BeforeRegisters, lib, "BeforeRegisters")
99 if ret := BeforeRegisters(GreaterThan16Bytes{&x, &y, &z}, 0x0F, 0xF0); ret != expectedUnsigned {
100 t.Fatalf("BeforeRegisters returned %#x wanted %#x", ret, expectedUnsigned)
101 }
102 }
103 {
104 type IntLessThan16Bytes struct {
105 x, y int64
106 }
107 var IntLessThan16BytesFn func(bytes IntLessThan16Bytes) int64
108 purego.RegisterLibFunc(&IntLessThan16BytesFn, lib, "IntLessThan16Bytes")
109 if ret := IntLessThan16BytesFn(IntLessThan16Bytes{0xDEAD0000, 0xBEEF}); ret != expectedUnsigned {
110 t.Fatalf("IntLessThan16BytesFn returned %#x wanted %#x", ret, expectedUnsigned)
111 }
112 }
113 {
114 type FloatLessThan16Bytes struct {
115 x, y float32
116 }
117 var FloatLessThan16BytesFn func(FloatLessThan16Bytes) float32
118 purego.RegisterLibFunc(&FloatLessThan16BytesFn, lib, "FloatLessThan16Bytes")
119 if ret := FloatLessThan16BytesFn(FloatLessThan16Bytes{3, 7}); ret != expectedFloat {
120 t.Fatalf("FloatLessThan16Bytes returned %f wanted %f", ret, expectedFloat)
121 }
122 }
123 {
124 type ThreeSmallFields struct {
125 x, y, z float32
126 }
127 var ThreeSmallFieldsFn func(ThreeSmallFields) float32
128 purego.RegisterLibFunc(&ThreeSmallFieldsFn, lib, "ThreeSmallFields")
129 if ret := ThreeSmallFieldsFn(ThreeSmallFields{1, 2, 7}); ret != expectedFloat {
130 t.Fatalf("ThreeSmallFields returned %f wanted %f", ret, expectedFloat)
131 }
132 }
133 {
134 type FloatAndInt struct {
135 x float32
136 y int32
137 }
138 var FloatAndIntFn func(FloatAndInt) float32
139 purego.RegisterLibFunc(&FloatAndIntFn, lib, "FloatAndInt")
140 if ret := FloatAndIntFn(FloatAndInt{3, 7}); ret != expectedFloat {
141 t.Fatalf("FloatAndIntFn returned %f wanted %f", ret, expectedFloat)
142 }
143 }
144 {
145 type DoubleStruct struct {
146 x float64
147 }
148 var DoubleStructFn func(DoubleStruct) float64
149 purego.RegisterLibFunc(&DoubleStructFn, lib, "DoubleStruct")
150 if ret := DoubleStructFn(DoubleStruct{10}); ret != expectedDouble {
151 t.Fatalf("DoubleStruct returned %f wanted %f", ret, expectedDouble)
152 }
153 }
154 {
155 type TwoDoubleStruct struct {
156 x, y float64
157 }
158 var TwoDoubleStructFn func(TwoDoubleStruct) float64
159 purego.RegisterLibFunc(&TwoDoubleStructFn, lib, "TwoDoubleStruct")
160 if ret := TwoDoubleStructFn(TwoDoubleStruct{3, 7}); ret != expectedDouble {
161 t.Fatalf("TwoDoubleStruct returned %f wanted %f", ret, expectedDouble)
162 }
163 }
164 {
165 type TwoDoubleTwoStruct struct {
166 x struct {
167 x, y float64
168 }
169 }
170 var TwoDoubleTwoStructFn func(TwoDoubleTwoStruct) float64
171 purego.RegisterLibFunc(&TwoDoubleTwoStructFn, lib, "TwoDoubleTwoStruct")
172 if ret := TwoDoubleTwoStructFn(TwoDoubleTwoStruct{x: struct{ x, y float64 }{x: 3, y: 7}}); ret != expectedDouble {
173 t.Fatalf("TwoDoubleTwoStruct returned %f wanted %f", ret, expectedDouble)
174 }
175 }
176 {
177 type ThreeDoubleStruct struct {
178 x, y, z float64
179 }
180 var ThreeDoubleStructFn func(ThreeDoubleStruct) float64
181 purego.RegisterLibFunc(&ThreeDoubleStructFn, lib, "ThreeDoubleStruct")
182 if ret := ThreeDoubleStructFn(ThreeDoubleStruct{1, 3, 6}); ret != expectedDouble {
183 t.Fatalf("ThreeDoubleStructFn returned %f wanted %f", ret, expectedDouble)
184 }
185 }
186 {
187 type LargeFloatStruct struct {
188 a, b, c, d, e, f float64
189 }
190 var LargeFloatStructFn func(LargeFloatStruct) float64
191 purego.RegisterLibFunc(&LargeFloatStructFn, lib, "LargeFloatStruct")
192 if ret := LargeFloatStructFn(LargeFloatStruct{1, 2, 3, 4, 5, -5}); ret != expectedDouble {
193 t.Fatalf("LargeFloatStructFn returned %f wanted %f", ret, expectedFloat)
194 }
195 var LargeFloatStructWithRegs func(a, b, c float64, s LargeFloatStruct) float64
196 purego.RegisterLibFunc(&LargeFloatStructWithRegs, lib, "LargeFloatStructWithRegs")
197 if ret := LargeFloatStructWithRegs(1, -1, 0, LargeFloatStruct{1, 2, 3, 4, 5, -5}); ret != expectedDouble {
198 t.Fatalf("LargeFloatStructWithRegs returned %f wanted %f", ret, expectedFloat)
199 }
200 }
201 {
202 type Rect struct {
203 x, y, w, h float64
204 }
205 var RectangleWithRegs func(a, b, c, d, e float64, rect Rect) float64
206 purego.RegisterLibFunc(&RectangleWithRegs, lib, "RectangleWithRegs")
207 if ret := RectangleWithRegs(1, 2, 3, 4, -2, Rect{1, 2, 3, -4}); ret != expectedDouble {
208 t.Fatalf("RectangleWithRegs returned %f wanted %f", ret, expectedDouble)
209 }
210 var RectangleSubtract func(rect Rect) float64
211 purego.RegisterLibFunc(&RectangleSubtract, lib, "RectangleSubtract")
212 if ret := RectangleSubtract(Rect{15, 5, 3, 7}); ret != expectedDouble {
213 t.Fatalf("RectangleSubtract returned %f wanted %f", ret, expectedDouble)
214 }
215 var Rectangle func(rect Rect) float64
216 purego.RegisterLibFunc(&Rectangle, lib, "Rectangle")
217 if ret := Rectangle(Rect{1, 2, 3, 4}); ret != expectedDouble {
218 t.Fatalf("Rectangle returned %f wanted %f", ret, expectedFloat)
219 }
220 }
221 {
222 type FloatArray struct {
223 a [2]float64
224 }
225 var FloatArrayFn func(rect FloatArray) float64
226 purego.RegisterLibFunc(&FloatArrayFn, lib, "FloatArray")
227 if ret := FloatArrayFn(FloatArray{a: [2]float64{3, 7}}); ret != expectedDouble {
228 t.Fatalf("FloatArray returned %f wanted %f", ret, expectedFloat)
229 }
230 }
231 {
232 type UnsignedChar4Bytes struct {
233 a, b, c, d byte
234 }
235 var UnsignedChar4BytesFn func(UnsignedChar4Bytes) uint32
236 purego.RegisterLibFunc(&UnsignedChar4BytesFn, lib, "UnsignedChar4Bytes")
237 if ret := UnsignedChar4BytesFn(UnsignedChar4Bytes{a: 0xDE, b: 0xAD, c: 0xBE, d: 0xEF}); ret != expectedUnsigned {
238 t.Fatalf("UnsignedChar4BytesFn returned %#x wanted %#x", ret, expectedUnsigned)
239 }
240 }
241 {
242 type UnsignedChar4BytesStruct struct {
243 x struct {
244 a byte
245 }
246 y struct {
247 b byte
248 }
249 z struct {
250 c byte
251 }
252 w struct {
253 d byte
254 }
255 }
256 var UnsignedChar4BytesStructFn func(UnsignedChar4BytesStruct) uint32
257 purego.RegisterLibFunc(&UnsignedChar4BytesStructFn, lib, "UnsignedChar4BytesStruct")
258 if ret := UnsignedChar4BytesStructFn(UnsignedChar4BytesStruct{
259 x: struct{ a byte }{a: 0xDE},
260 y: struct{ b byte }{b: 0xAD},
261 z: struct{ c byte }{c: 0xBE},
262 w: struct{ d byte }{d: 0xEF},
263 }); ret != expectedUnsigned {
264 t.Fatalf("UnsignedChar4BytesStructFn returned %#x wanted %#x", ret, expectedUnsigned)
265 }
266 }
267 {
268 type Short struct {
269 a, b, c, d uint16
270 }
271 var ShortFn func(Short) uint64
272 purego.RegisterLibFunc(&ShortFn, lib, "Short")
273 if ret := ShortFn(Short{a: 0xDEAD, b: 0xBEEF, c: 0xCAFE, d: 0xBABE}); ret != expectedLong {
274 t.Fatalf("ShortFn returned %#x wanted %#x", ret, expectedLong)
275 }
276 }
277 {
278 type Int struct {
279 a, b uint32
280 }
281 var IntFn func(Int) uint64
282 purego.RegisterLibFunc(&IntFn, lib, "Int")
283 if ret := IntFn(Int{a: 0xDEADBEEF, b: 0xCAFEBABE}); ret != expectedLong {
284 t.Fatalf("IntFn returned %#x wanted %#x", ret, expectedLong)
285 }
286 }
287 {
288 type Long struct {
289 a uint64
290 }
291 var LongFn func(Long) uint64
292 purego.RegisterLibFunc(&LongFn, lib, "Long")
293 if ret := LongFn(Long{a: 0xDEADBEEFCAFEBABE}); ret != expectedLong {
294 t.Fatalf("LongFn returned %#x wanted %#x", ret, expectedLong)
295 }
296 }
297 {
298 type Char8Bytes struct {
299 a, b, c, d, e, f, g, h int8
300 }
301 var Char8BytesFn func(Char8Bytes) int32
302 purego.RegisterLibFunc(&Char8BytesFn, lib, "Char8Bytes")
303 if ret := Char8BytesFn(Char8Bytes{a: -128, b: 127, c: 3, d: -88, e: -3, f: 34, g: -48, h: -20}); ret != expectedSigned {
304 t.Fatalf("Char8Bytes returned %d wanted %d", ret, expectedSigned)
305 }
306 }
307 {
308 type Odd struct {
309 a, b, c byte
310 }
311 var OddFn func(Odd) int32
312 purego.RegisterLibFunc(&OddFn, lib, "Odd")
313 if ret := OddFn(Odd{a: 12, b: 23, c: 46}); ret != expectedOdd {
314 t.Fatalf("OddFn returned %d wanted %d", ret, expectedOdd)
315 }
316 }
317 {
318 type Char2Short1 struct {
319 a, b byte
320 c uint16
321 }
322 var Char2Short1s func(Char2Short1) int32
323 purego.RegisterLibFunc(&Char2Short1s, lib, "Char2Short1s")
324 if ret := Char2Short1s(Char2Short1{a: 12, b: 23, c: 46}); ret != expectedOdd {
325 t.Fatalf("Char2Short1s returned %d wanted %d", ret, expectedOdd)
326 }
327 }
328 {
329 type SignedChar2Short1 struct {
330 a, b int8
331 c int16
332 }
333 var SignedChar2Short1Fn func(SignedChar2Short1) int32
334 purego.RegisterLibFunc(&SignedChar2Short1Fn, lib, "SignedChar2Short1")
335 if ret := SignedChar2Short1Fn(SignedChar2Short1{a: 100, b: -23, c: -200}); ret != expectedSigned {
336 t.Fatalf("SignedChar2Short1Fn returned %d wanted %d", ret, expectedSigned)
337 }
338 }
339 {
340 type Array4UnsignedChars struct {
341 a [4]uint8
342 }
343 var Array4UnsignedCharsFn func(chars Array4UnsignedChars) uint32
344 purego.RegisterLibFunc(&Array4UnsignedCharsFn, lib, "Array4UnsignedChars")
345 if ret := Array4UnsignedCharsFn(Array4UnsignedChars{a: [...]uint8{0xDE, 0xAD, 0xBE, 0xEF}}); ret != expectedUnsigned {
346 t.Fatalf("Array4UnsignedCharsFn returned %#x wanted %#x", ret, expectedUnsigned)
347 }
348 }
349 {
350 type Array3UnsignedChar struct {
351 a [3]uint8
352 }
353 var Array3UnsignedChars func(chars Array3UnsignedChar) uint32
354 purego.RegisterLibFunc(&Array3UnsignedChars, lib, "Array3UnsignedChars")
355 if ret := Array3UnsignedChars(Array3UnsignedChar{a: [...]uint8{0xDE, 0xAD, 0xBE}}); ret != expectedUnsigned {
356 t.Fatalf("Array4UnsignedCharsFn returned %#x wanted %#x", ret, expectedUnsigned)
357 }
358 }
359 {
360 type Array2UnsignedShort struct {
361 a [2]uint16
362 }
363 var Array2UnsignedShorts func(chars Array2UnsignedShort) uint32
364 purego.RegisterLibFunc(&Array2UnsignedShorts, lib, "Array2UnsignedShorts")
365 if ret := Array2UnsignedShorts(Array2UnsignedShort{a: [...]uint16{0xDEAD, 0xBEEF}}); ret != expectedUnsigned {
366 t.Fatalf("Array4UnsignedCharsFn returned %#x wanted %#x", ret, expectedUnsigned)
367 }
368 }
369 {
370 type Array4Chars struct {
371 a [4]int8
372 }
373 var Array4CharsFn func(chars Array4Chars) int32
374 purego.RegisterLibFunc(&Array4CharsFn, lib, "Array4Chars")
375 if ret := Array4CharsFn(Array4Chars{a: [...]int8{100, -127, 4, -100}}); ret != expectedSigned {
376 t.Fatalf("Array4CharsFn returned %#x wanted %#x", ret, expectedSigned)
377 }
378 }
379 {
380 type Array2Short struct {
381 a [2]int16
382 }
383 var Array2Shorts func(chars Array2Short) int32
384 purego.RegisterLibFunc(&Array2Shorts, lib, "Array2Shorts")
385 if ret := Array2Shorts(Array2Short{a: [...]int16{-333, 210}}); ret != expectedSigned {
386 t.Fatalf("Array4Shorts returned %#x wanted %#x", ret, expectedSigned)
387 }
388 }
389 {
390 type Array3Short struct {
391 a [3]int16
392 }
393 var Array3Shorts func(chars Array3Short) int32
394 purego.RegisterLibFunc(&Array3Shorts, lib, "Array3Shorts")
395 if ret := Array3Shorts(Array3Short{a: [...]int16{-333, 100, 110}}); ret != expectedSigned {
396 t.Fatalf("Array4Shorts returned %#x wanted %#x", ret, expectedSigned)
397 }
398 }
399 {
400 type BoolStruct struct {
401 b bool
402 }
403 var BoolStructFn func(BoolStruct) bool
404 purego.RegisterLibFunc(&BoolStructFn, lib, "BoolStruct")
405 if ret := BoolStructFn(BoolStruct{true}); ret != true {
406 t.Fatalf("BoolStructFn returned %v wanted %v", ret, true)
407 }
408 if ret := BoolStructFn(BoolStruct{false}); ret != false {
409 t.Fatalf("BoolStructFn returned %v wanted %v", ret, false)
410 }
411 }
412 {
413 type BoolFloat struct {
414 b bool
415 _ [3]byte // purego won't do padding for you so make sure it aligns properly with C struct
416 f float32
417 }
418 var BoolFloatFn func(BoolFloat) float32
419 purego.RegisterLibFunc(&BoolFloatFn, lib, "BoolFloat")
420 if ret := BoolFloatFn(BoolFloat{b: true, f: 10}); ret != expectedFloat {
421 t.Fatalf("BoolFloatFn returned %f wanted %f", ret, expectedFloat)
422 }
423 if ret := BoolFloatFn(BoolFloat{b: false, f: 10}); ret != -expectedFloat {
424 t.Fatalf("BoolFloatFn returned %f wanted %f", ret, -expectedFloat)
425 }
426 }
427 {
428 type point struct{ x, y float64 }
429 type size struct{ width, height float64 }
430 type Content struct {
431 point point
432 size size
433 }
434 var InitWithContentRect func(*int, Content, int32, int32, bool) uint64
435 purego.RegisterLibFunc(&InitWithContentRect, lib, "InitWithContentRect")
436 if ret := InitWithContentRect(new(int),
437 // These numbers are created so that when added together and then divided by 11 it produces 0xdeadbeef
438 Content{point{x: 41_000_000_000, y: 95_000_000}, size{width: 214_000, height: 149}},
439 15, 4, true); ret != expectedUnsigned {
440 t.Fatalf("InitWithContentRect returned %d wanted %#x", ret, expectedUnsigned)
441 }
442 }
443}
444
445func TestRegisterFunc_structReturns(t *testing.T) {
446 libFileName := filepath.Join(t.TempDir(), "structreturntest.so")
447 t.Logf("Build %v", libFileName)
448
449 if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "structtest", "structreturn_test.c")); err != nil {
450 t.Fatal(err)
451 }
452 defer os.Remove(libFileName)
453
454 lib, err := purego.Dlopen(libFileName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
455 if err != nil {
456 t.Fatalf("Dlopen(%q) failed: %v", libFileName, err)
457 }
458
459 {
460 type Empty struct{}
461 var ReturnEmpty func() Empty
462 purego.RegisterLibFunc(&ReturnEmpty, lib, "ReturnEmpty")
463 ret := ReturnEmpty()
464 _ = ret
465 }
466 {
467 type inner struct{ a int16 }
468 type StructInStruct struct {
469 a inner
470 b inner
471 c inner
472 }
473 var ReturnStructInStruct func(a, b, c int16) StructInStruct
474 purego.RegisterLibFunc(&ReturnStructInStruct, lib, "ReturnStructInStruct")
475 expected := StructInStruct{inner{^int16(0)}, inner{2}, inner{3}}
476 if ret := ReturnStructInStruct(^int16(0), 2, 3); ret != expected {
477 t.Fatalf("StructInStruct returned %+v wanted %+v", ret, expected)
478 }
479 }
480 {
481 type ThreeShorts struct{ a, b, c int16 }
482 var ReturnThreeShorts func(a, b, c int16) ThreeShorts
483 purego.RegisterLibFunc(&ReturnThreeShorts, lib, "ReturnThreeShorts")
484 expected := ThreeShorts{^int16(0), 2, 3}
485 if ret := ReturnThreeShorts(^int16(0), 2, 3); ret != expected {
486 t.Fatalf("ReturnThreeShorts returned %+v wanted %+v", ret, expected)
487 }
488 }
489 {
490 type FourShorts struct{ a, b, c, d int16 }
491 var ReturnFourShorts func(a, b, c, d int16) FourShorts
492 purego.RegisterLibFunc(&ReturnFourShorts, lib, "ReturnFourShorts")
493 expected := FourShorts{^int16(0), 2, 3, 4}
494 if ret := ReturnFourShorts(^int16(0), 2, 3, 4); ret != expected {
495 t.Fatalf("ReturnFourShorts returned %+v wanted %+v", ret, expected)
496 }
497 }
498 {
499 type OneLong struct{ a int64 }
500 var ReturnOneLong func(a int64) OneLong
501 purego.RegisterLibFunc(&ReturnOneLong, lib, "ReturnOneLong")
502 expected := OneLong{5}
503 if ret := ReturnOneLong(5); ret != expected {
504 t.Fatalf("ReturnOneLong returned %+v wanted %+v", ret, expected)
505 }
506 }
507 {
508 type TwoLongs struct{ a, b int64 }
509 var ReturnTwoLongs func(a, b int64) TwoLongs
510 purego.RegisterLibFunc(&ReturnTwoLongs, lib, "ReturnTwoLongs")
511 expected := TwoLongs{1, 2}
512 if ret := ReturnTwoLongs(1, 2); ret != expected {
513 t.Fatalf("ReturnTwoLongs returned %+v wanted %+v", ret, expected)
514 }
515 }
516 {
517 type ThreeLongs struct{ a, b, c int64 }
518 var ReturnThreeLongs func(a, b, c int64) ThreeLongs
519 purego.RegisterLibFunc(&ReturnThreeLongs, lib, "ReturnThreeLongs")
520 expected := ThreeLongs{1, 2, 3}
521 if ret := ReturnThreeLongs(1, 2, 3); ret != expected {
522 t.Fatalf("ReturnThreeLongs returned %+v wanted %+v", ret, expected)
523 }
524 }
525 {
526 type OneFloat struct{ a float32 }
527 var ReturnOneFloat func(a float32) OneFloat
528 purego.RegisterLibFunc(&ReturnOneFloat, lib, "ReturnOneFloat")
529 expected := OneFloat{1}
530 if ret := ReturnOneFloat(1); ret != expected {
531 t.Fatalf("ReturnOneFloat returned %+v wanted %+v", ret, expected)
532 }
533 }
534 {
535 type TwoFloats struct{ a, b float32 }
536 var ReturnTwoFloats func(a, b float32) TwoFloats
537 purego.RegisterLibFunc(&ReturnTwoFloats, lib, "ReturnTwoFloats")
538 expected := TwoFloats{3, 10}
539 if ret := ReturnTwoFloats(5, 2); ret != expected {
540 t.Fatalf("ReturnTwoFloats returned %+v wanted %+v", ret, expected)
541 }
542 }
543 {
544 type ThreeFloats struct{ a, b, c float32 }
545 var ReturnThreeFloats func(a, b, c float32) ThreeFloats
546 purego.RegisterLibFunc(&ReturnThreeFloats, lib, "ReturnThreeFloats")
547 expected := ThreeFloats{1, 2, 3}
548 if ret := ReturnThreeFloats(1, 2, 3); ret != expected {
549 t.Fatalf("ReturnThreeFloats returned %+v wanted %+v", ret, expected)
550 }
551 }
552 {
553 type OneDouble struct{ a float64 }
554 var ReturnOneDouble func(a float64) OneDouble
555 purego.RegisterLibFunc(&ReturnOneDouble, lib, "ReturnOneDouble")
556 expected := OneDouble{1}
557 if ret := ReturnOneDouble(1); ret != expected {
558 t.Fatalf("ReturnOneDouble returned %+v wanted %+v", ret, expected)
559 }
560 }
561 {
562 type TwoDoubles struct{ a, b float64 }
563 var ReturnTwoDoubles func(a, b float64) TwoDoubles
564 purego.RegisterLibFunc(&ReturnTwoDoubles, lib, "ReturnTwoDoubles")
565 expected := TwoDoubles{1, 2}
566 if ret := ReturnTwoDoubles(1, 2); ret != expected {
567 t.Fatalf("ReturnTwoDoubles returned %+v wanted %+v", ret, expected)
568 }
569 }
570 {
571 type ThreeDoubles struct{ a, b, c float64 }
572 var ReturnThreeDoubles func(a, b, c float64) ThreeDoubles
573 purego.RegisterLibFunc(&ReturnThreeDoubles, lib, "ReturnThreeDoubles")
574 expected := ThreeDoubles{1, 2, 3}
575 if ret := ReturnThreeDoubles(1, 2, 3); ret != expected {
576 t.Fatalf("ReturnThreeDoubles returned %+v wanted %+v", ret, expected)
577 }
578 }
579 {
580 type FourDoubles struct{ a, b, c, d float64 }
581 var ReturnFourDoubles func(a, b, c, d float64) FourDoubles
582 purego.RegisterLibFunc(&ReturnFourDoubles, lib, "ReturnFourDoubles")
583 expected := FourDoubles{1, 2, 3, 4}
584 if ret := ReturnFourDoubles(1, 2, 3, 4); ret != expected {
585 t.Fatalf("ReturnFourDoubles returned %+v wanted %+v", ret, expected)
586 }
587 }
588 {
589 type FourDoublesInternal struct {
590 f struct{ a, b float64 }
591 g struct{ c, d float64 }
592 }
593 var ReturnFourDoublesInternal func(a, b, c, d float64) FourDoublesInternal
594 purego.RegisterLibFunc(&ReturnFourDoublesInternal, lib, "ReturnFourDoublesInternal")
595 expected := FourDoublesInternal{f: struct{ a, b float64 }{a: 1, b: 2}, g: struct{ c, d float64 }{c: 3, d: 4}}
596 if ret := ReturnFourDoublesInternal(1, 2, 3, 4); ret != expected {
597 t.Fatalf("ReturnFourDoublesInternal returned %+v wanted %+v", ret, expected)
598 }
599 }
600 {
601 type FiveDoubles struct{ a, b, c, d, e float64 }
602 var ReturnFiveDoubles func(a, b, c, d, e float64) FiveDoubles
603 purego.RegisterLibFunc(&ReturnFiveDoubles, lib, "ReturnFiveDoubles")
604 expected := FiveDoubles{1, 2, 3, 4, 5}
605 if ret := ReturnFiveDoubles(1, 2, 3, 4, 5); ret != expected {
606 t.Fatalf("ReturnFiveDoubles returned %+v wanted %+v", ret, expected)
607 }
608 }
609 {
610 type OneFloatOneDouble struct {
611 a float32
612 _ float32
613 b float64
614 }
615 var ReturnOneFloatOneDouble func(a float32, b float64) OneFloatOneDouble
616 purego.RegisterLibFunc(&ReturnOneFloatOneDouble, lib, "ReturnOneFloatOneDouble")
617 expected := OneFloatOneDouble{a: 1, b: 2}
618 if ret := ReturnOneFloatOneDouble(1, 2); ret != expected {
619 t.Fatalf("ReturnOneFloatOneDouble returned %+v wanted %+v", ret, expected)
620 }
621 }
622 {
623 type OneDoubleOneFloat struct {
624 a float64
625 b float32
626 }
627 var ReturnOneDoubleOneFloat func(a float64, b float32) OneDoubleOneFloat
628 purego.RegisterLibFunc(&ReturnOneDoubleOneFloat, lib, "ReturnOneDoubleOneFloat")
629 expected := OneDoubleOneFloat{1, 2}
630 if ret := ReturnOneDoubleOneFloat(1, 2); ret != expected {
631 t.Fatalf("ReturnOneDoubleOneFloat returned %+v wanted %+v", ret, expected)
632 }
633 }
634 {
635 type Unaligned1 struct {
636 a int8
637 _ [1]int8
638 b int16
639 _ [1]int32
640 c int64
641 }
642 var ReturnUnaligned1 func(a int8, b int16, c int64) Unaligned1
643 purego.RegisterLibFunc(&ReturnUnaligned1, lib, "ReturnUnaligned1")
644 expected := Unaligned1{a: 1, b: 2, c: 3}
645 if ret := ReturnUnaligned1(1, 2, 3); ret != expected {
646 t.Fatalf("ReturnUnaligned1 returned %+v wanted %+v", ret, expected)
647 }
648 }
649 {
650 type Mixed1 struct {
651 a float32
652 b int32
653 }
654 var ReturnMixed1 func(a float32, b int32) Mixed1
655 purego.RegisterLibFunc(&ReturnMixed1, lib, "ReturnMixed1")
656 expected := Mixed1{1, 2}
657 if ret := ReturnMixed1(1, 2); ret != expected {
658 t.Fatalf("ReturnMixed1 returned %+v wanted %+v", ret, expected)
659 }
660 }
661 {
662 type Mixed2 struct {
663 a float32
664 b int32
665 c float32
666 d int32
667 }
668 var ReturnMixed2 func(a float32, b int32, c float32, d int32) Mixed2
669 purego.RegisterLibFunc(&ReturnMixed2, lib, "ReturnMixed2")
670 expected := Mixed2{1, 2, 3, 4}
671 if ret := ReturnMixed2(1, 2, 3, 4); ret != expected {
672 t.Fatalf("ReturnMixed2 returned %+v wanted %+v", ret, expected)
673 }
674 }
675 {
676 type Mixed3 struct {
677 a float32
678 b uint32
679 c float64
680 }
681 var ReturnMixed3 func(a float32, b uint32, c float64) Mixed3
682 purego.RegisterLibFunc(&ReturnMixed3, lib, "ReturnMixed3")
683 expected := Mixed3{1, 2, 3}
684 if ret := ReturnMixed3(1, 2, 3); ret != expected {
685 t.Fatalf("ReturnMixed3 returned %+v wanted %+v", ret, expected)
686 }
687 }
688 {
689 type Mixed4 struct {
690 a float64
691 b uint32
692 c float32
693 }
694 var ReturnMixed4 func(a float64, b uint32, c float32) Mixed4
695 purego.RegisterLibFunc(&ReturnMixed4, lib, "ReturnMixed4")
696 expected := Mixed4{1, 2, 3}
697 if ret := ReturnMixed4(1, 2, 3); ret != expected {
698 t.Fatalf("ReturnMixed4 returned %+v wanted %+v", ret, expected)
699 }
700 }
701 {
702 type Ptr1 struct {
703 a *int64
704 b unsafe.Pointer
705 }
706 var ReturnPtr1 func(a *int64, b unsafe.Pointer) Ptr1
707 purego.RegisterLibFunc(&ReturnPtr1, lib, "ReturnPtr1")
708 a, b := new(int64), new(struct{})
709 expected := Ptr1{a, unsafe.Pointer(b)}
710 if ret := ReturnPtr1(a, unsafe.Pointer(b)); ret != expected {
711 t.Fatalf("ReturnPtr1 returned %+v wanted %+v", ret, expected)
712 }
713 runtime.KeepAlive(a)
714 runtime.KeepAlive(b)
715 }
716}