github.com/ebitengine/purego@v0.8.0-alpha.2.0.20240512170805-6cd12240d332/struct_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2024 The Ebitengine Authors 3 4 //go:build darwin && (arm64 || amd64) 5 6 package purego_test 7 8 import ( 9 "os" 10 "path/filepath" 11 "runtime" 12 "testing" 13 "unsafe" 14 15 "github.com/ebitengine/purego" 16 ) 17 18 func 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 445 func 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 }